Skip to content

Commit b7e8042

Browse files
authored
Merge pull request #827 from monopole/fix826
Improve error handling during var resolution.
2 parents b67179e + 6bfd7cf commit b7e8042

File tree

8 files changed

+150
-44
lines changed

8 files changed

+150
-44
lines changed

pkg/commands/build/build_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ import (
2222
"sigs.k8s.io/kustomize/pkg/constants"
2323
)
2424

25+
func TestNewOptionsToSilenceCodeInspectionError(t *testing.T) {
26+
if NewOptions("foo", "bar") == nil {
27+
t.Fatal("could not make new options")
28+
}
29+
}
30+
2531
func TestBuildValidate(t *testing.T) {
2632
var cases = []struct {
2733
name string

pkg/commands/edit/add/flagsandargs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func (a *flagsAndArgs) ExpandFileSource(fSys fs.FileSystem) error {
9494
if key != "" {
9595
if len(result) != 1 {
9696
return fmt.Errorf(
97-
"'pattern '%s' catches files %v, should catch only one.", pattern, result)
97+
"'pattern '%s' catches files %v, should catch only one", pattern, result)
9898
}
9999
fileSource := fmt.Sprintf("%s=%s", key, result[0])
100100
results = append(results, fileSource)

pkg/expansion/expand.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ func MappingFuncFor(context ...map[string]string) func(string) string {
4444
return val
4545
}
4646
}
47-
4847
return syntaxWrap(input)
4948
}
5049
}

pkg/expansion/expand_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ func TestMapReference(t *testing.T) {
4646
"BLU": "$(ZOO)-2",
4747
}
4848

49-
serviceEnv := map[string]string{}
50-
51-
mapping := MappingFuncFor(declaredEnv, serviceEnv)
49+
mapping := MappingFuncFor(declaredEnv)
5250

5351
for _, env := range envs {
5452
declaredEnv[env.Name] = Expand(env.Value, mapping)

pkg/resmap/resmap.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ func (m ResMap) GetMatchingIds(matches IdMatcher) []resid.ResId {
4646
return result
4747
}
4848

49-
// DemandOneGvknMatchForId find the matched resource by Group/Version/Kind and Name
50-
func (m ResMap) DemandOneGvknMatchForId(inputId resid.ResId) (*resource.Resource, bool) {
51-
result := m.GetMatchingIds(inputId.GvknEquals)
52-
if len(result) == 1 {
53-
return m[result[0]], true
54-
}
55-
return nil, false
56-
}
57-
5849
// EncodeAsYaml encodes a ResMap to YAML; encoded objects separated by `---`.
5950
func (m ResMap) EncodeAsYaml() ([]byte, error) {
6051
var ids []resid.ResId

pkg/resmap/resmap_test.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,35 +92,34 @@ func TestDemandOneGvknMatchForId(t *testing.T) {
9292
}),
9393
}
9494

95-
_, ok := rm1.DemandOneGvknMatchForId(
96-
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"))
97-
if !ok {
98-
t.Fatal("Expected single map entry but got none")
95+
result := rm1.GetMatchingIds(
96+
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1").GvknEquals)
97+
if len(result) != 1 {
98+
t.Fatalf("Expected single map entry but got %v", result)
9999
}
100100

101101
// confirm that ns and prefix are not included in match
102-
_, ok = rm1.DemandOneGvknMatchForId(
103-
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix", "ns"))
104-
if !ok {
105-
t.Fatal("Expected single map entry but got none")
102+
result = rm1.GetMatchingIds(
103+
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix", "ns").GvknEquals)
104+
if len(result) != 1 {
105+
t.Fatalf("Expected single map entry but got %v", result)
106106
}
107107

108108
// confirm that name is matched correctly
109-
result, ok := rm1.DemandOneGvknMatchForId(
110-
resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns1"))
111-
if ok {
109+
result = rm1.GetMatchingIds(
110+
resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns1").GvknEquals)
111+
if len(result) > 0 {
112112
t.Fatalf("Expected no map entries but got %v", result)
113113
}
114114

115115
cmap2 := gvk.Gvk{Version: "v2", Kind: "ConfigMap"}
116116

117117
// confirm that gvk is matched correctly
118-
result, ok = rm1.DemandOneGvknMatchForId(
119-
resid.NewResIdWithPrefixNamespace(cmap2, "cm2", "prefix1", "ns1"))
120-
if ok {
118+
result = rm1.GetMatchingIds(
119+
resid.NewResIdWithPrefixNamespace(cmap2, "cm2", "prefix1", "ns1").GvknEquals)
120+
if len(result) > 0 {
121121
t.Fatalf("Expected no map entries but got %v", result)
122122
}
123-
124123
}
125124

126125
func TestFilterBy(t *testing.T) {

pkg/target/resaccumulator.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package target
1818

1919
import (
2020
"fmt"
21-
"log"
2221
"sigs.k8s.io/kustomize/pkg/resid"
2322
"sigs.k8s.io/kustomize/pkg/resmap"
2423
"sigs.k8s.io/kustomize/pkg/transformers"
@@ -101,17 +100,27 @@ func (ra *ResAccumulator) MergeAccumulator(other *ResAccumulator) (err error) {
101100
// for substitution wherever the $(var.Name) occurs.
102101
func (ra *ResAccumulator) makeVarReplacementMap() (map[string]string, error) {
103102
result := map[string]string{}
104-
for _, v := range ra.varSet.Set() {
105-
id := resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name)
106-
if r, found := ra.resMap.DemandOneGvknMatchForId(id); found {
107-
s, err := r.GetFieldValue(v.FieldRef.FieldPath)
103+
for _, v := range ra.Vars() {
104+
matched := ra.resMap.GetMatchingIds(
105+
resid.NewResId(v.ObjRef.GVK(), v.ObjRef.Name).GvknEquals)
106+
if len(matched) > 1 {
107+
return nil, fmt.Errorf(
108+
"found %d resId matches for var %s "+
109+
"(unable to disambiguate)",
110+
len(matched), v)
111+
}
112+
if len(matched) == 1 {
113+
s, err := ra.resMap[matched[0]].GetFieldValue(v.FieldRef.FieldPath)
108114
if err != nil {
109-
return nil, fmt.Errorf("field path err for var: %+v", v)
115+
return nil, fmt.Errorf(
116+
"field specified in var '%v' "+
117+
"not found in corresponding resource", v)
110118
}
111119
result[v.Name] = s
112120
} else {
113-
// Should this be an error?
114-
log.Printf("var %v defined but not used", v)
121+
return nil, fmt.Errorf(
122+
"var '%v' cannot be mapped to a field "+
123+
"in the set of known resources", v)
115124
}
116125
}
117126
return result, nil

pkg/target/resaccumulator_test.go

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ import (
3030
"sigs.k8s.io/kustomize/pkg/types"
3131
)
3232

33-
func TestResolveVars(t *testing.T) {
33+
func makeResAccumulator() (*ResAccumulator, *resource.Factory, error) {
3434
ra := MakeEmptyAccumulator()
3535
err := ra.MergeConfig(config.MakeDefaultConfig())
3636
if err != nil {
37-
t.Fatalf("unexpected err: %v", err)
37+
return nil, nil, err
3838
}
3939
rf := resource.NewFactory(
4040
kunstruct.NewKunstructuredFactoryImpl())
@@ -55,8 +55,8 @@ func TestResolveVars(t *testing.T) {
5555
map[string]interface{}{
5656
"command": []interface{}{
5757
"myserver",
58-
"--somebackendService $(FOO)",
59-
"--yetAnother $(BAR)",
58+
"--somebackendService $(SERVICE_ONE)",
59+
"--yetAnother $(SERVICE_TWO)",
6060
},
6161
},
6262
},
@@ -85,14 +85,23 @@ func TestResolveVars(t *testing.T) {
8585
},
8686
}),
8787
})
88+
return ra, rf, nil
89+
}
90+
91+
func TestResolveVarsHappy(t *testing.T) {
92+
ra, _, err := makeResAccumulator()
93+
if err != nil {
94+
t.Fatalf("unexpected err: %v", err)
95+
}
8896
err = ra.MergeVars([]types.Var{
8997
{
90-
Name: "FOO",
98+
Name: "SERVICE_ONE",
9199
ObjRef: types.Target{
92100
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
93101
Name: "backendOne"},
94-
}, {
95-
Name: "BAR",
102+
},
103+
{
104+
Name: "SERVICE_TWO",
96105
ObjRef: types.Target{
97106
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
98107
Name: "backendTwo"},
@@ -111,6 +120,101 @@ func TestResolveVars(t *testing.T) {
111120
}
112121
}
113122

123+
func TestResolveVarsVarNeedsDisambiguation(t *testing.T) {
124+
ra, rf, err := makeResAccumulator()
125+
if err != nil {
126+
t.Fatalf("unexpected err: %v", err)
127+
}
128+
ra.MergeResourcesWithErrorOnIdCollision(resmap.ResMap{
129+
resid.NewResIdWithPrefixNamespace(
130+
gvk.Gvk{Version: "v1", Kind: "Service"},
131+
"backendOne", "", "fooNamespace"): rf.FromMap(
132+
map[string]interface{}{
133+
"apiVersion": "v1",
134+
"kind": "Service",
135+
"metadata": map[string]interface{}{
136+
"name": "backendOne",
137+
},
138+
}),
139+
})
140+
141+
err = ra.MergeVars([]types.Var{
142+
{
143+
Name: "SERVICE_ONE",
144+
ObjRef: types.Target{
145+
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
146+
Name: "backendOne",
147+
},
148+
},
149+
})
150+
if err != nil {
151+
t.Fatalf("unexpected err: %v", err)
152+
}
153+
err = ra.ResolveVars()
154+
if err == nil {
155+
t.Fatalf("expected error")
156+
}
157+
if !strings.Contains(
158+
err.Error(), "unable to disambiguate") {
159+
t.Fatalf("unexpected err: %v", err)
160+
}
161+
}
162+
163+
func TestResolveVarsGoodResIdBadField(t *testing.T) {
164+
ra, _, err := makeResAccumulator()
165+
if err != nil {
166+
t.Fatalf("unexpected err: %v", err)
167+
}
168+
err = ra.MergeVars([]types.Var{
169+
{
170+
Name: "SERVICE_ONE",
171+
ObjRef: types.Target{
172+
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
173+
Name: "backendOne"},
174+
FieldRef: types.FieldSelector{FieldPath: "nope_nope_nope"},
175+
},
176+
})
177+
if err != nil {
178+
t.Fatalf("unexpected err: %v", err)
179+
}
180+
err = ra.ResolveVars()
181+
if err == nil {
182+
t.Fatalf("expected error")
183+
}
184+
if !strings.Contains(
185+
err.Error(),
186+
"not found in corresponding resource") {
187+
t.Fatalf("unexpected err: %v", err)
188+
}
189+
}
190+
191+
func TestResolveVarsUnmappableVar(t *testing.T) {
192+
ra, _, err := makeResAccumulator()
193+
if err != nil {
194+
t.Fatalf("unexpected err: %v", err)
195+
}
196+
err = ra.MergeVars([]types.Var{
197+
{
198+
Name: "SERVICE_THREE",
199+
ObjRef: types.Target{
200+
Gvk: gvk.Gvk{Version: "v1", Kind: "Service"},
201+
Name: "doesNotExist"},
202+
},
203+
})
204+
if err != nil {
205+
t.Fatalf("unexpected err: %v", err)
206+
}
207+
err = ra.ResolveVars()
208+
if err == nil {
209+
t.Fatalf("expected error")
210+
}
211+
if !strings.Contains(
212+
err.Error(),
213+
"cannot be mapped to a field in the set of known resources") {
214+
t.Fatalf("unexpected err: %v", err)
215+
}
216+
}
217+
114218
func find(name string, resMap resmap.ResMap) *resource.Resource {
115219
for k, v := range resMap {
116220
if k.Name() == name {

0 commit comments

Comments
 (0)