Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit15daad1

Browse files
committed
fix: validate that parameter names are unique
1 parent1288a83 commit15daad1

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

‎coderd/util/slice/slice.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package slice
22

3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
38
// SameElements returns true if the 2 lists have the same elements in any
49
// order.
510
funcSameElements[Tcomparable](a []T,b []T)bool {
@@ -67,3 +72,16 @@ func OverlapCompare[T any](a []T, b []T, equal func(a, b T) bool) bool {
6772
funcNew[Tany](items...T) []T {
6873
returnitems
6974
}
75+
76+
// JoinWithConjunction joins a slice of strings with commas except for the last
77+
// two which are joined with "and".
78+
funcJoinWithConjunction(s []string)string {
79+
last:=len(s)-1
80+
iflast==0 {
81+
returns[last]
82+
}
83+
returnfmt.Sprintf("%s and %s",
84+
strings.Join(s[:last],", "),
85+
s[last],
86+
)
87+
}

‎coderd/util/slice/slice_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ func TestOverlap(t *testing.T) {
8383
)
8484
}
8585

86+
funcTestJoinWithConjunction(t*testing.T) {
87+
t.Parallel()
88+
require.Equal(t,"foo",slice.JoinWithConjunction([]string{"foo"}))
89+
require.Equal(t,"foo and bar",slice.JoinWithConjunction([]string{"foo","bar"}))
90+
require.Equal(t,"foo, bar and baz",slice.JoinWithConjunction([]string{"foo","bar","baz"}))
91+
}
92+
8693
funcassertSetOverlaps[Tcomparable](t*testing.T,overlapbool,a []T,b []T) {
8794
t.Helper()
8895
for_,e:=rangea {

‎provisioner/terraform/resources.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package terraform
22

33
import (
4+
"fmt"
45
"strings"
56

67
"github.com/awalterschulze/gographviz"
@@ -10,6 +11,7 @@ import (
1011

1112
"github.com/coder/terraform-provider-coder/provider"
1213

14+
"github.com/coder/coder/coderd/util/slice"
1315
"github.com/coder/coder/codersdk"
1416
"github.com/coder/coder/provisioner"
1517
"github.com/coder/coder/provisionersdk/proto"
@@ -473,6 +475,7 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string, rawParameterNa
473475
}
474476
}
475477

478+
varduplicatedNames []string
476479
parameters:=make([]*proto.RichParameter,0)
477480
for_,resource:=rangeorderedRichParametersResources(tfResourcesRichParameters,rawParameterNames) {
478481
varparam provider.Parameter
@@ -536,9 +539,32 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string, rawParameterNa
536539
})
537540
}
538541
}
542+
543+
// Check if this parameter duplicates an existing parameter.
544+
formattedName:=fmt.Sprintf("%q",protoParam.Name)
545+
if!slice.Contains(duplicatedNames,formattedName)&&
546+
slice.ContainsCompare(parameters,protoParam,func(a,b*proto.RichParameter)bool {
547+
returna.Name==b.Name
548+
}) {
549+
duplicatedNames=append(duplicatedNames,formattedName)
550+
}
551+
539552
parameters=append(parameters,protoParam)
540553
}
541554

555+
// Enforce that parameters must be uniquely named.
556+
iflen(duplicatedNames)>0 {
557+
s:=""
558+
iflen(duplicatedNames)==1 {
559+
s="s"
560+
}
561+
returnnil,xerrors.Errorf(
562+
"coder_parameter names must be unique but %s appear%s multiple times",
563+
slice.JoinWithConjunction(duplicatedNames),
564+
s,
565+
)
566+
}
567+
542568
// A map is used to ensure we don't have duplicates!
543569
gitAuthProvidersMap:=map[string]struct{}{}
544570
for_,tfResources:=rangetfResourcesByLabel {

‎provisioner/terraform/resources_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package terraform_test
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"os"
67
"path/filepath"
78
"runtime"
@@ -584,6 +585,69 @@ func TestAppSlugValidation(t *testing.T) {
584585
require.ErrorContains(t,err,"duplicate app slug")
585586
}
586587

588+
funcTestParameterValidation(t*testing.T) {
589+
t.Parallel()
590+
591+
// nolint:dogsled
592+
_,filename,_,_:=runtime.Caller(0)
593+
594+
// Load the rich-parameters state file and edit it.
595+
dir:=filepath.Join(filepath.Dir(filename),"testdata","rich-parameters")
596+
tfPlanRaw,err:=os.ReadFile(filepath.Join(dir,"rich-parameters.tfplan.json"))
597+
require.NoError(t,err)
598+
vartfPlan tfjson.Plan
599+
err=json.Unmarshal(tfPlanRaw,&tfPlan)
600+
require.NoError(t,err)
601+
tfPlanGraph,err:=os.ReadFile(filepath.Join(dir,"rich-parameters.tfplan.dot"))
602+
require.NoError(t,err)
603+
604+
// Change all names to be identical.
605+
varnames []string
606+
for_,resource:=rangetfPlan.PriorState.Values.RootModule.Resources {
607+
ifresource.Type=="coder_parameter" {
608+
resource.AttributeValues["name"]="identical"
609+
names=append(names,resource.Name)
610+
}
611+
}
612+
613+
state,err:=terraform.ConvertState([]*tfjson.StateModule{tfPlan.PriorState.Values.RootModule},string(tfPlanGraph),names)
614+
require.Nil(t,state)
615+
require.Error(t,err)
616+
require.ErrorContains(t,err,"coder_parameter names must be unique but\"identical\" appears multiple times")
617+
618+
// Make two sets of identical names.
619+
count:=0
620+
names=nil
621+
for_,resource:=rangetfPlan.PriorState.Values.RootModule.Resources {
622+
ifresource.Type=="coder_parameter" {
623+
resource.AttributeValues["name"]=fmt.Sprintf("identical-%d",count%2)
624+
names=append(names,resource.Name)
625+
count++
626+
}
627+
}
628+
629+
state,err=terraform.ConvertState([]*tfjson.StateModule{tfPlan.PriorState.Values.RootModule},string(tfPlanGraph),names)
630+
require.Nil(t,state)
631+
require.Error(t,err)
632+
require.ErrorContains(t,err,"coder_parameter names must be unique but\"identical-0\" and\"identical-1\" appear multiple times")
633+
634+
// Once more with three sets.
635+
count=0
636+
names=nil
637+
for_,resource:=rangetfPlan.PriorState.Values.RootModule.Resources {
638+
ifresource.Type=="coder_parameter" {
639+
resource.AttributeValues["name"]=fmt.Sprintf("identical-%d",count%3)
640+
names=append(names,resource.Name)
641+
count++
642+
}
643+
}
644+
645+
state,err=terraform.ConvertState([]*tfjson.StateModule{tfPlan.PriorState.Values.RootModule},string(tfPlanGraph),names)
646+
require.Nil(t,state)
647+
require.Error(t,err)
648+
require.ErrorContains(t,err,"coder_parameter names must be unique but\"identical-0\",\"identical-1\" and\"identical-2\" appear multiple times")
649+
}
650+
587651
funcTestInstanceTypeAssociation(t*testing.T) {
588652
t.Parallel()
589653
typetcstruct {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp