Skip to content

Commit 07c34f1

Browse files
authored
Merge pull request #41 from jaypipes/sorted-printer-columns
always sort additional printer columns
2 parents 338d010 + d4becdc commit 07c34f1

File tree

5 files changed

+188
-104
lines changed

5 files changed

+188
-104
lines changed

pkg/generate/codedeploy_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,21 @@ func TestCodeDeploy_Deployment(t *testing.T) {
110110
// But sadly, has no Update or Delete operation :(
111111
assert.Nil(crd.Ops.Update)
112112
assert.Nil(crd.Ops.Delete)
113+
114+
// We marked the fields, "ApplicationName", "DeploymentGroupName",
115+
// "DeploymentConfigName and "Description" as printer columns in the
116+
// generator.yaml. Let's make sure that they are always returned in sorted
117+
// order.
118+
expPrinterColNames := []string{
119+
"ApplicationName",
120+
"DeploymentConfigName",
121+
"DeploymentGroupName",
122+
"Description",
123+
}
124+
gotPrinterCols := crd.AdditionalPrinterColumns()
125+
gotPrinterColNames := []string{}
126+
for _, pc := range gotPrinterCols {
127+
gotPrinterColNames = append(gotPrinterColNames, pc.Name)
128+
}
129+
assert.Equal(expPrinterColNames, gotPrinterColNames)
113130
}

pkg/generate/generator.go

+2-10
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,7 @@ func (g *Generator) GetCRDs() ([]*ackmodel.CRD, error) {
141141
)
142142
if found {
143143
memberNames := names.New(targetFieldName)
144-
field := crd.AddSpecField(memberNames, memberShapeRef)
145-
146-
if fieldConfig.IsPrintable {
147-
crd.AddSpecPrintableColumn(field)
148-
}
144+
crd.AddSpecField(memberNames, memberShapeRef)
149145
} else {
150146
// This is a compile-time failure, just bomb out...
151147
msg := fmt.Sprintf(
@@ -214,11 +210,7 @@ func (g *Generator) GetCRDs() ([]*ackmodel.CRD, error) {
214210
)
215211
if found {
216212
memberNames := names.New(targetFieldName)
217-
field := crd.AddStatusField(memberNames, memberShapeRef)
218-
219-
if fieldConfig.IsPrintable {
220-
crd.AddStatusPrintableColumn(field)
221-
}
213+
crd.AddStatusField(memberNames, memberShapeRef)
222214
} else {
223215
// This is a compile-time failure, just bomb out...
224216
msg := fmt.Sprintf(

pkg/generate/testdata/models/apis/codedeploy/0000-00-00/generator.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,13 @@ resources:
44
errors:
55
404:
66
code: DeploymentDoesNotExistException
7+
# below, we're testing printer columns end up sorted properly in the CRD
8+
fields:
9+
DeploymentGroupName:
10+
is_printable: true
11+
ApplicationName:
12+
is_printable: true
13+
DeploymentConfigName:
14+
is_printable: true
15+
Description:
16+
is_printable: true

pkg/model/crd.go

+17-94
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package model
1515

1616
import (
17-
"fmt"
1817
"sort"
1918
"strings"
2019

@@ -58,14 +57,6 @@ func (ops Ops) IterOps() []*awssdkmodel.Operation {
5857
return res
5958
}
6059

61-
// PrinterColumn represents a single field in the CRD's Spec or Status objects
62-
type PrinterColumn struct {
63-
CRD *CRD
64-
Name string
65-
Type string
66-
JSONPath string
67-
}
68-
6960
// CRD describes a single top-level resource in an AWS service API
7061
type CRD struct {
7162
sdkAPI *SDKAPI
@@ -75,10 +66,9 @@ type CRD struct {
7566
Plural string
7667
// Ops are the CRUD operations controlling this resource
7768
Ops Ops
78-
// AdditionalPrinterColumns is an array of PrinterColumn objects
69+
// additionalPrinterColumns is an array of PrinterColumn objects
7970
// representing the printer column settings for the CRD
80-
// AdditionalPrinterColumns field.
81-
AdditionalPrinterColumns []*PrinterColumn
71+
additionalPrinterColumns []*PrinterColumn
8272
// SpecFields is a map, keyed by the **original SDK member name** of
8373
// Field objects representing those fields in the CRD's Spec struct
8474
// field.
@@ -178,22 +168,29 @@ func (r *CRD) InputFieldRename(
178168
func (r *CRD) AddSpecField(
179169
memberNames names.Names,
180170
shapeRef *awssdkmodel.ShapeRef,
181-
) *Field {
182-
fieldConfigs := r.cfg.ResourceFields(r.Names.Original)
183-
f := newField(r, memberNames, shapeRef, fieldConfigs[memberNames.Original])
171+
) {
172+
fConfigs := r.cfg.ResourceFields(r.Names.Original)
173+
fConfig := fConfigs[memberNames.Original]
174+
f := newField(r, memberNames, shapeRef, fConfig)
175+
if fConfig != nil && fConfig.IsPrintable {
176+
r.addSpecPrintableColumn(f)
177+
}
184178
r.SpecFields[memberNames.Original] = f
185-
return f
186179
}
187180

188181
// AddStatusField adds a new Field of a given name and shape into the Status
189182
// field of a CRD
190183
func (r *CRD) AddStatusField(
191184
memberNames names.Names,
192185
shapeRef *awssdkmodel.ShapeRef,
193-
) *Field {
194-
f := newField(r, memberNames, shapeRef, nil)
186+
) {
187+
fConfigs := r.cfg.ResourceFields(r.Names.Original)
188+
fConfig := fConfigs[memberNames.Original]
189+
f := newField(r, memberNames, shapeRef, fConfig)
190+
if fConfig != nil && fConfig.IsPrintable {
191+
r.addStatusPrintableColumn(f)
192+
}
195193
r.StatusFields[memberNames.Original] = f
196-
return f
197194
}
198195

199196
// AddTypeImport adds an entry in the CRD's TypeImports map for an import line
@@ -218,80 +215,6 @@ func (r *CRD) SpecFieldNames() []string {
218215
return res
219216
}
220217

221-
// AddPrintableColumn adds an entry to the list of additional printer columns
222-
// using the given path and field types.
223-
func (r *CRD) AddPrintableColumn(
224-
field *Field,
225-
jsonPath string,
226-
) *PrinterColumn {
227-
fieldColumnType := field.GoTypeElem
228-
229-
// Printable columns must be primitives supported by the OpenAPI list of data
230-
// types as defined by
231-
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
232-
// This maps Go type to OpenAPI type.
233-
acceptableColumnMaps := map[string]string{
234-
"string": "string",
235-
"boolean": "boolean",
236-
"int": "integer",
237-
"int8": "integer",
238-
"int16": "integer",
239-
"int32": "integer",
240-
"int64": "integer",
241-
"uint": "integer",
242-
"uint8": "integer",
243-
"uint16": "integer",
244-
"uint32": "integer",
245-
"uint64": "integer",
246-
"uintptr": "integer",
247-
"float32": "number",
248-
"float64": "number",
249-
}
250-
printColumnType, exists := acceptableColumnMaps[fieldColumnType]
251-
252-
if !exists {
253-
msg := fmt.Sprintf(
254-
"GENERATION FAILURE! Unable to generate a printer column for the field %s that has type %s.",
255-
field.Names.Camel, fieldColumnType,
256-
)
257-
panic(msg)
258-
return nil
259-
}
260-
261-
column := &PrinterColumn{
262-
CRD: r,
263-
Name: field.Names.Camel,
264-
Type: printColumnType,
265-
JSONPath: jsonPath,
266-
}
267-
r.AdditionalPrinterColumns = append(r.AdditionalPrinterColumns, column)
268-
return column
269-
}
270-
271-
// AddSpecPrintableColumn adds an entry to the list of additional printer columns
272-
// using the path of the given spec field.
273-
func (r *CRD) AddSpecPrintableColumn(
274-
field *Field,
275-
) *PrinterColumn {
276-
return r.AddPrintableColumn(
277-
field,
278-
//TODO(nithomso): Ideally we'd use `r.cfg.PrefixConfig.SpecField` but it uses uppercase
279-
fmt.Sprintf("%s.%s", ".spec", field.Names.CamelLower),
280-
)
281-
}
282-
283-
// AddStatusPrintableColumn adds an entry to the list of additional printer columns
284-
// using the path of the given status field.
285-
func (r *CRD) AddStatusPrintableColumn(
286-
field *Field,
287-
) *PrinterColumn {
288-
return r.AddPrintableColumn(
289-
field,
290-
//TODO(nithomso): Ideally we'd use `r.cfg.PrefixConfig.StatusField` but it uses uppercase
291-
fmt.Sprintf("%s.%s", ".status", field.Names.CamelLower),
292-
)
293-
}
294-
295218
// UnpacksAttributesMap returns true if the underlying API has
296219
// Get{Resource}Attributes/Set{Resource}Attributes API calls that map real,
297220
// schema'd fields to a raw `map[string]*string` for this resource (see SNS and
@@ -470,7 +393,7 @@ func NewCRD(
470393
Kind: kind,
471394
Plural: plural,
472395
Ops: ops,
473-
AdditionalPrinterColumns: make([]*PrinterColumn, 0),
396+
additionalPrinterColumns: make([]*PrinterColumn, 0),
474397
SpecFields: map[string]*Field{},
475398
StatusFields: map[string]*Field{},
476399
ShortNames: cfg.ResourceShortNames(kind),

pkg/model/printer_column.go

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package model
15+
16+
import (
17+
"fmt"
18+
"sort"
19+
)
20+
21+
// PrinterColumn represents a single field in the CRD's Spec or Status objects
22+
type PrinterColumn struct {
23+
CRD *CRD
24+
Name string
25+
Type string
26+
JSONPath string
27+
}
28+
29+
// By can sort two PrinterColumns
30+
type By func(a, b *PrinterColumn) bool
31+
32+
// Sort does an in-place sort of the supplied printer columns
33+
func (by By) Sort(subject []*PrinterColumn) {
34+
pcs := printerColumnSorter{
35+
cols: subject,
36+
by: by,
37+
}
38+
sort.Sort(pcs)
39+
}
40+
41+
// printerColumnSorter sorts printer columns by name
42+
type printerColumnSorter struct {
43+
cols []*PrinterColumn
44+
by By
45+
}
46+
47+
// Len implements sort.Interface.Len
48+
func (pcs printerColumnSorter) Len() int {
49+
return len(pcs.cols)
50+
}
51+
52+
// Swap implements sort.Interface.Swap
53+
func (pcs printerColumnSorter) Swap(i, j int) {
54+
pcs.cols[i], pcs.cols[j] = pcs.cols[j], pcs.cols[i]
55+
}
56+
57+
// Less implements sort.Interface.Less
58+
func (pcs printerColumnSorter) Less(i, j int) bool {
59+
return pcs.by(pcs.cols[i], pcs.cols[j])
60+
}
61+
62+
// AdditionalPrinterColumns returns a sorted list of PrinterColumn structs for
63+
// the resource
64+
func (r CRD) AdditionalPrinterColumns() []*PrinterColumn {
65+
byName := func(a, b *PrinterColumn) bool {
66+
return a.Name < b.Name
67+
}
68+
By(byName).Sort(r.additionalPrinterColumns)
69+
return r.additionalPrinterColumns
70+
}
71+
72+
// addPrintableColumn adds an entry to the list of additional printer columns
73+
// using the given path and field types.
74+
func (r *CRD) addPrintableColumn(
75+
field *Field,
76+
jsonPath string,
77+
) {
78+
fieldColumnType := field.GoTypeElem
79+
80+
// Printable columns must be primitives supported by the OpenAPI list of data
81+
// types as defined by
82+
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
83+
// This maps Go type to OpenAPI type.
84+
acceptableColumnMaps := map[string]string{
85+
"string": "string",
86+
"boolean": "boolean",
87+
"int": "integer",
88+
"int8": "integer",
89+
"int16": "integer",
90+
"int32": "integer",
91+
"int64": "integer",
92+
"uint": "integer",
93+
"uint8": "integer",
94+
"uint16": "integer",
95+
"uint32": "integer",
96+
"uint64": "integer",
97+
"uintptr": "integer",
98+
"float32": "number",
99+
"float64": "number",
100+
}
101+
printColumnType, exists := acceptableColumnMaps[fieldColumnType]
102+
103+
if !exists {
104+
msg := fmt.Sprintf(
105+
"GENERATION FAILURE! Unable to generate a printer column for the field %s that has type %s.",
106+
field.Names.Camel, fieldColumnType,
107+
)
108+
panic(msg)
109+
}
110+
111+
column := &PrinterColumn{
112+
CRD: r,
113+
Name: field.Names.Camel,
114+
Type: printColumnType,
115+
JSONPath: jsonPath,
116+
}
117+
r.additionalPrinterColumns = append(r.additionalPrinterColumns, column)
118+
}
119+
120+
// addSpecPrintableColumn adds an entry to the list of additional printer columns
121+
// using the path of the given spec field.
122+
func (r *CRD) addSpecPrintableColumn(
123+
field *Field,
124+
) {
125+
r.addPrintableColumn(
126+
field,
127+
//TODO(nithomso): Ideally we'd use `r.cfg.PrefixConfig.SpecField` but it uses uppercase
128+
fmt.Sprintf("%s.%s", ".spec", field.Names.CamelLower),
129+
)
130+
}
131+
132+
// addStatusPrintableColumn adds an entry to the list of additional printer columns
133+
// using the path of the given status field.
134+
func (r *CRD) addStatusPrintableColumn(
135+
field *Field,
136+
) {
137+
r.addPrintableColumn(
138+
field,
139+
//TODO(nithomso): Ideally we'd use `r.cfg.PrefixConfig.StatusField` but it uses uppercase
140+
fmt.Sprintf("%s.%s", ".status", field.Names.CamelLower),
141+
)
142+
}

0 commit comments

Comments
 (0)