Skip to content

Commit 0fba82b

Browse files
committed
CRD generation: remove status before writing
It's tricky to get the existing CRD types to not include the status, so we instead allow for filtering of the map just before writing. Issue #456
1 parent 99e7fbc commit 0fba82b

File tree

5 files changed

+61
-12
lines changed

5 files changed

+61
-12
lines changed

pkg/crd/gen.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ func (Generator) CheckFilter() loader.NodeFilter {
8585
func (Generator) RegisterMarkers(into *markers.Registry) error {
8686
return crdmarkers.Register(into)
8787
}
88+
89+
// transformRemoveCRDStatus ensures we do not write the CRD status field.
90+
func transformRemoveCRDStatus(obj map[string]interface{}) error {
91+
delete(obj, "status")
92+
return nil
93+
}
94+
8895
func (g Generator) Generate(ctx *genall.GenerationContext) error {
8996
parser := &Parser{
9097
Collector: ctx.Collector,
@@ -145,7 +152,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
145152
} else {
146153
fileName = fmt.Sprintf("%s_%s.%s.yaml", crdRaw.Spec.Group, crdRaw.Spec.Names.Plural, crdVersions[i])
147154
}
148-
if err := ctx.WriteYAML(fileName, crd); err != nil {
155+
if err := ctx.WriteYAML(fileName, []interface{}{crd}, genall.WithTransform(transformRemoveCRDStatus)); err != nil {
149156
return err
150157
}
151158
}

pkg/crd/spec.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,5 @@ func (p *Parser) NeedCRDFor(groupKind schema.GroupKind, maxDescLen *int) {
164164
packages[0].AddError(fmt.Errorf("CRD for %s with version(s) %v does not serve any version", groupKind, crd.Spec.Versions))
165165
}
166166

167-
// NB(directxman12): CRD's status doesn't have omitempty markers, which means things
168-
// get serialized as null, which causes the validator to freak out. Manually set
169-
// these to empty till we get a better solution.
170-
crd.Status.Conditions = []apiext.CustomResourceDefinitionCondition{}
171-
crd.Status.StoredVersions = []string{}
172-
173167
p.CustomResourceDefinitions[groupKind] = crd
174168
}

pkg/genall/genall.go

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ limitations under the License.
1717
package genall
1818

1919
import (
20+
"encoding/json"
2021
"fmt"
2122
"io"
2223
"io/ioutil"
2324
"os"
2425

2526
"golang.org/x/tools/go/packages"
26-
"sigs.k8s.io/yaml"
27+
rawyaml "gopkg.in/yaml.v2"
2728

2829
"sigs.k8s.io/controller-tools/pkg/loader"
2930
"sigs.k8s.io/controller-tools/pkg/markers"
@@ -120,18 +121,30 @@ type GenerationContext struct {
120121
InputRule
121122
}
122123

124+
// WriteYAMLOptions implements the Options Pattern for WriteYAML.
125+
type WriteYAMLOptions struct {
126+
transform func(obj map[string]interface{}) error
127+
}
128+
129+
// WithTransform applies a transformation to objects just before writing them.
130+
func WithTransform(transform func(obj map[string]interface{}) error) *WriteYAMLOptions {
131+
return &WriteYAMLOptions{
132+
transform: transform,
133+
}
134+
}
135+
123136
// WriteYAML writes the given objects out, serialized as YAML, using the
124137
// context's OutputRule. Objects are written as separate documents, separated
125138
// from each other by `---` (as per the YAML spec).
126-
func (g GenerationContext) WriteYAML(itemPath string, objs ...interface{}) error {
139+
func (g GenerationContext) WriteYAML(itemPath string, objs []interface{}, options ...*WriteYAMLOptions) error {
127140
out, err := g.Open(nil, itemPath)
128141
if err != nil {
129142
return err
130143
}
131144
defer out.Close()
132145

133146
for _, obj := range objs {
134-
yamlContent, err := yaml.Marshal(obj)
147+
yamlContent, err := yamlMarshal(obj, options...)
135148
if err != nil {
136149
return err
137150
}
@@ -147,6 +160,41 @@ func (g GenerationContext) WriteYAML(itemPath string, objs ...interface{}) error
147160
return nil
148161
}
149162

163+
// yamlMarshal is based on sigs.k8s.io/yaml.Marshal, but allows for transforming the final data before writing.
164+
func yamlMarshal(o interface{}, options ...*WriteYAMLOptions) ([]byte, error) {
165+
j, err := json.Marshal(o)
166+
if err != nil {
167+
return nil, fmt.Errorf("error marshaling into JSON: %v", err)
168+
}
169+
170+
return yamlJSONToYAMLWithFilter(j, options...)
171+
}
172+
173+
// yamlJSONToYAMLWithFilter is based on sigs.k8s.io/yaml.JSONToYAML, but allows for transforming the final data before writing.
174+
func yamlJSONToYAMLWithFilter(j []byte, options ...*WriteYAMLOptions) ([]byte, error) {
175+
// Convert the JSON to an object.
176+
var jsonObj map[string]interface{}
177+
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
178+
// Go JSON library doesn't try to pick the right number type (int, float,
179+
// etc.) when unmarshalling to interface{}, it just picks float64
180+
// universally. go-yaml does go through the effort of picking the right
181+
// number type, so we can preserve number type throughout this process.
182+
if err := rawyaml.Unmarshal(j, &jsonObj); err != nil {
183+
return nil, err
184+
}
185+
186+
for _, option := range options {
187+
if option.transform != nil {
188+
if err := option.transform(jsonObj); err != nil {
189+
return nil, err
190+
}
191+
}
192+
}
193+
194+
// Marshal this object into YAML.
195+
return rawyaml.Marshal(jsonObj)
196+
}
197+
150198
// ReadFile reads the given boilerplate artifact using the context's InputRule.
151199
func (g GenerationContext) ReadFile(path string) ([]byte, error) {
152200
file, err := g.OpenForRead(path)

pkg/rbac/parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,5 +263,5 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
263263
return nil
264264
}
265265

266-
return ctx.WriteYAML("role.yaml", objs...)
266+
return ctx.WriteYAML("role.yaml", objs)
267267
}

pkg/webhook/parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ func (Generator) Generate(ctx *genall.GenerationContext) error {
389389
} else {
390390
fileName = fmt.Sprintf("manifests.%s.yaml", k)
391391
}
392-
if err := ctx.WriteYAML(fileName, v...); err != nil {
392+
if err := ctx.WriteYAML(fileName, v); err != nil {
393393
return err
394394
}
395395
}

0 commit comments

Comments
 (0)