Skip to content

Commit bb572d4

Browse files
author
Antoine Pelisse
committed
Add new cli command to generate fieldset
Creates a new command-line mode to generate fieldsets (as we work on new formats, it can be useful to generate some fieldsets to compare them). Also adds a test and some golden data for what the fieldset is supposed to look like.
1 parent 960c3cc commit bb572d4

File tree

5 files changed

+179
-2
lines changed

5 files changed

+179
-2
lines changed

internal/cli/main_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,30 @@ func TestCompare(t *testing.T) {
188188
})
189189
}
190190
}
191+
192+
func TestFieldSet(t *testing.T) {
193+
cases := []testCase{{
194+
options: Options{
195+
schemaPath: testdata("k8s-schema.yaml"),
196+
fieldset: testdata("pod.yaml"),
197+
typeName: "io.k8s.api.core.v1.Pod",
198+
},
199+
expectedOutputPath: testdata("podset.json"),
200+
}}
201+
202+
for _, tt := range cases {
203+
tt := tt
204+
t.Run(tt.options.fieldset, func(t *testing.T) {
205+
op, err := tt.options.Resolve()
206+
if err != nil {
207+
t.Fatal(err)
208+
}
209+
var b bytes.Buffer
210+
err = op.Execute(&b)
211+
if err != nil {
212+
t.Errorf("unexpected error: %v", err)
213+
}
214+
tt.checkOutput(t, b.Bytes())
215+
})
216+
}
217+
}

internal/cli/operation.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,30 @@ func (v validation) Execute(_ io.Writer) error {
5656
return err
5757
}
5858

59+
type fieldset struct {
60+
operationBase
61+
62+
fileToUse string
63+
}
64+
65+
func (f fieldset) Execute(w io.Writer) error {
66+
tv, err := f.parseFile(f.fileToUse)
67+
if err != nil {
68+
return err
69+
}
70+
71+
empty, err := f.parser.Type(f.typeName).FromYAML(typed.YAMLObject("{}"))
72+
if err != nil {
73+
return err
74+
}
75+
c, err := empty.Compare(tv)
76+
if err != nil {
77+
return err
78+
}
79+
80+
return c.Added.ToJSONStream(w)
81+
}
82+
5983
type listTypes struct {
6084
operationBase
6185
}

internal/cli/options.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
)
2929

3030
var (
31-
ErrTooManyOperations = errors.New("exactly one of --merge, --compare, or --validate must be provided")
31+
ErrTooManyOperations = errors.New("exactly one of --merge, --compare, --validate or --fieldset must be provided")
3232
ErrNeedTwoArgs = errors.New("--merge and --compare require both --lhs and --rhs")
3333
)
3434

@@ -43,6 +43,7 @@ type Options struct {
4343
validatePath string
4444
merge bool
4545
compare bool
46+
fieldset string
4647

4748
// arguments for merge or compare
4849
lhsPath string
@@ -63,6 +64,7 @@ func (o *Options) AddFlags(fs *flag.FlagSet) {
6364
fs.StringVar(&o.validatePath, "validate", "", "Path to a file to perform a validation operation on.")
6465
fs.BoolVar(&o.merge, "merge", false, "Perform a merge operation between --lhs and --rhs")
6566
fs.BoolVar(&o.compare, "compare", false, "Perform a compare operation between --lhs and --rhs")
67+
fs.StringVar(&o.fieldset, "fieldset", "", "Path to a file for which we should build a fieldset.")
6668

6769
fs.StringVar(&o.lhsPath, "lhs", "", "Path to a file containing the left hand side of the operation")
6870
fs.StringVar(&o.rhsPath, "rhs", "", "Path to a file containing the right hand side of the operation")
@@ -95,7 +97,7 @@ func (o *Options) Resolve() (Operation, error) {
9597

9698
// Count how many operations were requested
9799
c := map[bool]int{true: 1}
98-
count := c[o.merge] + c[o.compare] + c[o.validatePath != ""] + c[o.listTypes]
100+
count := c[o.merge] + c[o.compare] + c[o.validatePath != ""] + c[o.listTypes] + c[o.fieldset != ""]
99101
if count > 1 {
100102
return nil, ErrTooManyOperations
101103
}
@@ -115,6 +117,8 @@ func (o *Options) Resolve() (Operation, error) {
115117
return nil, ErrNeedTwoArgs
116118
}
117119
return compare{base, o.lhsPath, o.rhsPath}, nil
120+
case o.fieldset != "":
121+
return fieldset{base, o.fieldset}, nil
118122
}
119123
return nil, errors.New("no operation requested")
120124
}

internal/testdata/pod.yaml

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
labels:
5+
app: some-app
6+
plugin1: some-value
7+
plugin2: some-value
8+
plugin3: some-value
9+
plugin4: some-value
10+
name: some-name
11+
namespace: default
12+
ownerReferences:
13+
- apiVersion: apps/v1
14+
blockOwnerDeletion: true
15+
controller: true
16+
kind: ReplicaSet
17+
name: some-name
18+
uid: 0a9d2b9e-779e-11e7-b422-42010a8001be
19+
spec:
20+
containers:
21+
- args:
22+
- one
23+
- two
24+
- three
25+
- four
26+
- five
27+
- six
28+
- seven
29+
- eight
30+
- nine
31+
env:
32+
- name: VAR_3
33+
valueFrom:
34+
secretKeyRef:
35+
key: some-other-key
36+
name: some-oher-name
37+
- name: VAR_2
38+
valueFrom:
39+
secretKeyRef:
40+
key: other-key
41+
name: other-name
42+
- name: VAR_1
43+
valueFrom:
44+
secretKeyRef:
45+
key: some-key
46+
name: some-name
47+
image: some-image-name
48+
imagePullPolicy: IfNotPresent
49+
name: some-name
50+
resources:
51+
requests:
52+
cpu: "0"
53+
terminationMessagePath: /dev/termination-log
54+
terminationMessagePolicy: File
55+
volumeMounts:
56+
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
57+
name: default-token-hu5jz
58+
readOnly: true
59+
dnsPolicy: ClusterFirst
60+
nodeName: node-name
61+
priority: 0
62+
restartPolicy: Always
63+
schedulerName: default-scheduler
64+
securityContext: {}
65+
serviceAccount: default
66+
serviceAccountName: default
67+
terminationGracePeriodSeconds: 30
68+
tolerations:
69+
- effect: NoExecute
70+
key: node.kubernetes.io/not-ready
71+
operator: Exists
72+
tolerationSeconds: 300
73+
- effect: NoExecute
74+
key: node.kubernetes.io/unreachable
75+
operator: Exists
76+
tolerationSeconds: 300
77+
volumes:
78+
- name: default-token-hu5jz
79+
secret:
80+
defaultMode: 420
81+
secretName: default-token-hu5jz
82+
status:
83+
conditions:
84+
- lastProbeTime: null
85+
lastTransitionTime: "2019-07-08T09:31:18Z"
86+
status: "True"
87+
type: Initialized
88+
- lastProbeTime: null
89+
lastTransitionTime: "2019-07-08T09:41:59Z"
90+
status: "True"
91+
type: Ready
92+
- lastProbeTime: null
93+
lastTransitionTime: null
94+
status: "True"
95+
type: ContainersReady
96+
- lastProbeTime: null
97+
lastTransitionTime: "2019-07-08T09:31:18Z"
98+
status: "True"
99+
type: PodScheduled
100+
containerStatuses:
101+
- containerID: docker://885e82a1ed0b7356541bb410a0126921ac42439607c09875cd8097dd5d7b5376
102+
image: some-image-name
103+
imageID: docker-pullable://some-image-id
104+
lastState:
105+
terminated:
106+
containerID: docker://d57290f9e00fad626b20d2dd87a3cf69bbc22edae07985374f86a8b2b4e39565
107+
exitCode: 255
108+
finishedAt: "2019-07-08T09:39:09Z"
109+
reason: Error
110+
startedAt: "2019-07-08T09:38:54Z"
111+
name: name
112+
ready: true
113+
restartCount: 6
114+
state:
115+
running:
116+
startedAt: "2019-07-08T09:41:59Z"
117+
hostIP: 10.0.0.1
118+
phase: Running
119+
podIP: 10.0.0.1
120+
qosClass: BestEffort
121+
startTime: "2019-07-08T09:31:18Z"

internal/testdata/podset.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"f:apiVersion":{},"f:kind":{},"f:metadata":{"f:labels":{"f:app":{},"f:plugin1":{},"f:plugin2":{},"f:plugin3":{},"f:plugin4":{},".":{}},"f:name":{},"f:namespace":{},"f:ownerReferences":{"k:{\"uid\":\"0a9d2b9e-779e-11e7-b422-42010a8001be\"}":{"f:apiVersion":{},"f:blockOwnerDeletion":{},"f:controller":{},"f:kind":{},"f:name":{},"f:uid":{},".":{}},".":{}},".":{}},"f:spec":{"f:containers":{"k:{\"name\":\"some-name\"}":{"f:args":{},"f:env":{"k:{\"name\":\"VAR_1\"}":{"f:name":{},"f:valueFrom":{"f:secretKeyRef":{"f:key":{},"f:name":{},".":{}},".":{}},".":{}},"k:{\"name\":\"VAR_2\"}":{"f:name":{},"f:valueFrom":{"f:secretKeyRef":{"f:key":{},"f:name":{},".":{}},".":{}},".":{}},"k:{\"name\":\"VAR_3\"}":{"f:name":{},"f:valueFrom":{"f:secretKeyRef":{"f:key":{},"f:name":{},".":{}},".":{}},".":{}},".":{}},"f:image":{},"f:imagePullPolicy":{},"f:name":{},"f:resources":{"f:requests":{"f:cpu":{},".":{}},".":{}},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{},"f:volumeMounts":{"k:{\"mountPath\":\"/var/run/secrets/kubernetes.io/serviceaccount\"}":{"f:mountPath":{},"f:name":{},"f:readOnly":{},".":{}},".":{}},".":{}},".":{}},"f:dnsPolicy":{},"f:nodeName":{},"f:priority":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:serviceAccount":{},"f:serviceAccountName":{},"f:terminationGracePeriodSeconds":{},"f:tolerations":{},"f:volumes":{},".":{}},"f:status":{"f:conditions":{"k:{\"type\":\"ContainersReady\"}":{"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{},".":{}},"k:{\"type\":\"Initialized\"}":{"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{},".":{}},"k:{\"type\":\"PodScheduled\"}":{"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{},".":{}},"k:{\"type\":\"Ready\"}":{"f:lastProbeTime":{},"f:lastTransitionTime":{},"f:status":{},"f:type":{},".":{}},".":{}},"f:containerStatuses":{},"f:hostIP":{},"f:phase":{},"f:podIP":{},"f:qosClass":{},"f:startTime":{},".":{}}}

0 commit comments

Comments
 (0)