Skip to content

Commit 4eb2757

Browse files
committed
Further isolate unstructured with factories.
1 parent 3cdfbd8 commit 4eb2757

31 files changed

+525
-348
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package k8sdeps
18+
19+
import (
20+
"io"
21+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
22+
"sigs.k8s.io/kustomize/pkg/ifc"
23+
)
24+
25+
// KustKunstructuredFactory hides construction using apimachinery types.
26+
type KustKunstructuredFactory struct {
27+
decoder ifc.Decoder
28+
}
29+
30+
var _ ifc.KunstructuredFactory = &KustKunstructuredFactory{}
31+
32+
// NewKustKunstructuredFactory returns a factory.
33+
func NewKustKunstructuredFactory(d ifc.Decoder) ifc.KunstructuredFactory {
34+
return &KustKunstructuredFactory{decoder: d}
35+
}
36+
37+
// SliceFromBytes returns a slice of Kunstructured.
38+
func (kf *KustKunstructuredFactory) SliceFromBytes(
39+
in []byte) ([]ifc.Kunstructured, error) {
40+
kf.decoder.SetInput(in)
41+
var result []ifc.Kunstructured
42+
var err error
43+
for err == nil || isEmptyYamlError(err) {
44+
var out unstructured.Unstructured
45+
err = kf.decoder.Decode(&out)
46+
if err == nil {
47+
result = append(result, &UnstructAdapter{Unstructured: out})
48+
}
49+
}
50+
if err != io.EOF {
51+
return nil, err
52+
}
53+
return result, nil
54+
}
55+
56+
// FromMap returns an instance of Kunstructured.
57+
func (kf *KustKunstructuredFactory) FromMap(
58+
m map[string]interface{}) ifc.Kunstructured {
59+
return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}}
60+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package k8sdeps
18+
19+
import (
20+
"reflect"
21+
"testing"
22+
23+
"sigs.k8s.io/kustomize/pkg/ifc"
24+
)
25+
26+
func TestSliceFromBytes(t *testing.T) {
27+
factory := NewKustKunstructuredFactory(NewKustDecoder())
28+
testConfigMap := factory.FromMap(
29+
map[string]interface{}{
30+
"apiVersion": "v1",
31+
"kind": "ConfigMap",
32+
"metadata": map[string]interface{}{
33+
"name": "winnie",
34+
},
35+
})
36+
37+
tests := []struct {
38+
name string
39+
input []byte
40+
expectedOut []ifc.Kunstructured
41+
expectedErr bool
42+
}{
43+
{
44+
name: "garbage",
45+
input: []byte("garbageIn: garbageOut"),
46+
expectedOut: []ifc.Kunstructured{},
47+
expectedErr: true,
48+
},
49+
{
50+
name: "noBytes",
51+
input: []byte{},
52+
expectedOut: []ifc.Kunstructured{},
53+
expectedErr: false,
54+
},
55+
{
56+
name: "goodJson",
57+
input: []byte(`
58+
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
59+
`),
60+
expectedOut: []ifc.Kunstructured{testConfigMap},
61+
expectedErr: false,
62+
},
63+
{
64+
name: "goodYaml1",
65+
input: []byte(`
66+
apiVersion: v1
67+
kind: ConfigMap
68+
metadata:
69+
name: winnie
70+
`),
71+
expectedOut: []ifc.Kunstructured{testConfigMap},
72+
expectedErr: false,
73+
},
74+
{
75+
name: "goodYaml2",
76+
input: []byte(`
77+
apiVersion: v1
78+
kind: ConfigMap
79+
metadata:
80+
name: winnie
81+
---
82+
apiVersion: v1
83+
kind: ConfigMap
84+
metadata:
85+
name: winnie
86+
`),
87+
expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap},
88+
expectedErr: false,
89+
},
90+
{
91+
name: "garbageInOneOfTwoObjects",
92+
input: []byte(`
93+
apiVersion: v1
94+
kind: ConfigMap
95+
metadata:
96+
name: winnie
97+
---
98+
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
99+
`),
100+
expectedOut: []ifc.Kunstructured{},
101+
expectedErr: true,
102+
},
103+
}
104+
105+
for _, test := range tests {
106+
rs, err := factory.SliceFromBytes(test.input)
107+
if test.expectedErr && err == nil {
108+
t.Fatalf("%v: should return error", test.name)
109+
}
110+
if !test.expectedErr && err != nil {
111+
t.Fatalf("%v: unexpected error: %s", test.name, err)
112+
}
113+
if len(rs) != len(test.expectedOut) {
114+
t.Fatalf("%s: length mismatch %d != %d",
115+
test.name, len(rs), len(test.expectedOut))
116+
}
117+
for i := range rs {
118+
if !reflect.DeepEqual(test.expectedOut[i], rs[i]) {
119+
t.Fatalf("%s: Got: %v\nexpected:%v",
120+
test.name, test.expectedOut[i], rs[i])
121+
}
122+
}
123+
}
124+
}

internal/k8sdeps/unstructadapter.go

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package k8sdeps
218

319
import (
420
"encoding/json"
521
"fmt"
6-
"io"
722
"strings"
823

924
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -37,35 +52,6 @@ func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) {
3752
return &UnstructAdapter{Unstructured: u}, err
3853
}
3954

40-
// NewKunstructuredFromMap returns a new instance of Kunstructured.
41-
func NewKunstructuredFromMap(m map[string]interface{}) ifc.Kunstructured {
42-
return NewKunstructuredFromUnstruct(unstructured.Unstructured{Object: m})
43-
}
44-
45-
// NewKunstructuredFromUnstruct returns a new instance of Kunstructured.
46-
func NewKunstructuredFromUnstruct(u unstructured.Unstructured) ifc.Kunstructured {
47-
return &UnstructAdapter{Unstructured: u}
48-
}
49-
50-
// NewKunstructuredSliceFromBytes unmarshalls bytes into a Kunstructured slice.
51-
func NewKunstructuredSliceFromBytes(
52-
in []byte, decoder ifc.Decoder) ([]ifc.Kunstructured, error) {
53-
decoder.SetInput(in)
54-
var result []ifc.Kunstructured
55-
var err error
56-
for err == nil || isEmptyYamlError(err) {
57-
var out unstructured.Unstructured
58-
err = decoder.Decode(&out)
59-
if err == nil {
60-
result = append(result, &UnstructAdapter{Unstructured: out})
61-
}
62-
}
63-
if err != io.EOF {
64-
return nil, err
65-
}
66-
return result, nil
67-
}
68-
6955
// GetGvk returns the Gvk name of the object.
7056
func (fs *UnstructAdapter) GetGvk() gvk.Gvk {
7157
return gvk.FromSchemaGvk(fs.GroupVersionKind())

internal/k8sdeps/unstructadapter_test.go

Lines changed: 19 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,28 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
package k8sdeps
218

319
import (
4-
"reflect"
5-
"sigs.k8s.io/kustomize/pkg/ifc"
620
"testing"
721
)
822

9-
var testConfigMap = NewKunstructuredFromMap(
10-
map[string]interface{}{
11-
"apiVersion": "v1",
12-
"kind": "ConfigMap",
13-
"metadata": map[string]interface{}{
14-
"name": "winnie",
15-
},
16-
})
17-
18-
func TestNewKunstructuredSliceFromBytes(t *testing.T) {
19-
tests := []struct {
20-
name string
21-
input []byte
22-
expectedOut []ifc.Kunstructured
23-
expectedErr bool
24-
}{
25-
{
26-
name: "garbage",
27-
input: []byte("garbageIn: garbageOut"),
28-
expectedOut: []ifc.Kunstructured{},
29-
expectedErr: true,
30-
},
31-
{
32-
name: "noBytes",
33-
input: []byte{},
34-
expectedOut: []ifc.Kunstructured{},
35-
expectedErr: false,
36-
},
37-
{
38-
name: "goodJson",
39-
input: []byte(`
40-
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
41-
`),
42-
expectedOut: []ifc.Kunstructured{testConfigMap},
43-
expectedErr: false,
44-
},
45-
{
46-
name: "goodYaml1",
47-
input: []byte(`
48-
apiVersion: v1
49-
kind: ConfigMap
50-
metadata:
51-
name: winnie
52-
`),
53-
expectedOut: []ifc.Kunstructured{testConfigMap},
54-
expectedErr: false,
55-
},
56-
{
57-
name: "goodYaml2",
58-
input: []byte(`
59-
apiVersion: v1
60-
kind: ConfigMap
61-
metadata:
62-
name: winnie
63-
---
64-
apiVersion: v1
65-
kind: ConfigMap
66-
metadata:
67-
name: winnie
68-
`),
69-
expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap},
70-
expectedErr: false,
71-
},
72-
{
73-
name: "garbageInOneOfTwoObjects",
74-
input: []byte(`
75-
apiVersion: v1
76-
kind: ConfigMap
77-
metadata:
78-
name: winnie
79-
---
80-
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
81-
`),
82-
expectedOut: []ifc.Kunstructured{},
83-
expectedErr: true,
84-
},
85-
}
86-
87-
for _, test := range tests {
88-
rs, err := NewKunstructuredSliceFromBytes(
89-
test.input, NewKustDecoder())
90-
if test.expectedErr && err == nil {
91-
t.Fatalf("%v: should return error", test.name)
92-
}
93-
if !test.expectedErr && err != nil {
94-
t.Fatalf("%v: unexpected error: %s", test.name, err)
95-
}
96-
if len(rs) != len(test.expectedOut) {
97-
t.Fatalf("%s: length mismatch %d != %d",
98-
test.name, len(rs), len(test.expectedOut))
99-
}
100-
for i := range rs {
101-
if !reflect.DeepEqual(test.expectedOut[i], rs[i]) {
102-
t.Fatalf("%s: Got: %v\nexpected:%v",
103-
test.name, test.expectedOut[i], rs[i])
104-
}
105-
}
106-
}
107-
}
108-
10923
func TestGetFieldValue(t *testing.T) {
110-
funStruct := NewKunstructuredFromMap(map[string]interface{}{
24+
factory := NewKustKunstructuredFactory(NewKustDecoder())
25+
kunstructured := factory.FromMap(map[string]interface{}{
11126
"Kind": "Service",
11227
"metadata": map[string]interface{}{
11328
"labels": map[string]string{
@@ -150,7 +65,7 @@ func TestGetFieldValue(t *testing.T) {
15065
}
15166

15267
for _, test := range tests {
153-
s, err := funStruct.GetFieldValue(test.pathToField)
68+
s, err := kunstructured.GetFieldValue(test.pathToField)
15469
if test.errorExpected && err == nil {
15570
t.Fatalf("should return error, but no error returned")
15671
} else {

kustomize.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func main() {
2828
defer glog.Flush()
2929

3030
if err := commands.NewDefaultCommand(
31+
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()),
3132
k8sdeps.NewKustDecoder(),
3233
k8sdeps.NewKustValidator(),
3334
k8sdeps.NewKustHash()).Execute(); err != nil {

0 commit comments

Comments
 (0)