Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 CRD generation: remove status before writing #630

Merged
merged 2 commits into from
Feb 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion pkg/crd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ func (Generator) CheckFilter() loader.NodeFilter {
func (Generator) RegisterMarkers(into *markers.Registry) error {
return crdmarkers.Register(into)
}

// transformRemoveCRDStatus ensures we do not write the CRD status field.
func transformRemoveCRDStatus(obj map[string]interface{}) error {
delete(obj, "status")
return nil
}

func (g Generator) Generate(ctx *genall.GenerationContext) error {
parser := &Parser{
Collector: ctx.Collector,
Expand Down Expand Up @@ -145,7 +152,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
} else {
fileName = fmt.Sprintf("%s_%s.%s.yaml", crdRaw.Spec.Group, crdRaw.Spec.Names.Plural, crdVersions[i])
}
if err := ctx.WriteYAML(fileName, crd); err != nil {
if err := ctx.WriteYAML(fileName, []interface{}{crd}, genall.WithTransform(transformRemoveCRDStatus)); err != nil {
return err
}
}
Expand Down
6 changes: 0 additions & 6 deletions pkg/crd/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,5 @@ func (p *Parser) NeedCRDFor(groupKind schema.GroupKind, maxDescLen *int) {
packages[0].AddError(fmt.Errorf("CRD for %s with version(s) %v does not serve any version", groupKind, crd.Spec.Versions))
}

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

p.CustomResourceDefinitions[groupKind] = crd
}
6 changes: 0 additions & 6 deletions pkg/crd/testdata/gen/bar.example.com_foos.v1beta1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,3 @@ spec:
- name: foo
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
6 changes: 0 additions & 6 deletions pkg/crd/testdata/gen/bar.example.com_foos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,3 @@ spec:
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
6 changes: 0 additions & 6 deletions pkg/crd/testdata/plural/plural.example.com_testquotas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,3 @@ spec:
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
6 changes: 0 additions & 6 deletions pkg/crd/testdata/testdata.kubebuilder.io_cronjobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7498,9 +7498,3 @@ spec:
storage: false
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
54 changes: 51 additions & 3 deletions pkg/genall/genall.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ limitations under the License.
package genall

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"

"golang.org/x/tools/go/packages"
"sigs.k8s.io/yaml"
rawyaml "gopkg.in/yaml.v2"

"sigs.k8s.io/controller-tools/pkg/loader"
"sigs.k8s.io/controller-tools/pkg/markers"
Expand Down Expand Up @@ -120,18 +121,30 @@ type GenerationContext struct {
InputRule
}

// WriteYAMLOptions implements the Options Pattern for WriteYAML.
type WriteYAMLOptions struct {
transform func(obj map[string]interface{}) error
}

// WithTransform applies a transformation to objects just before writing them.
func WithTransform(transform func(obj map[string]interface{}) error) *WriteYAMLOptions {
return &WriteYAMLOptions{
transform: transform,
}
}

// WriteYAML writes the given objects out, serialized as YAML, using the
// context's OutputRule. Objects are written as separate documents, separated
// from each other by `---` (as per the YAML spec).
func (g GenerationContext) WriteYAML(itemPath string, objs ...interface{}) error {
func (g GenerationContext) WriteYAML(itemPath string, objs []interface{}, options ...*WriteYAMLOptions) error {
out, err := g.Open(nil, itemPath)
if err != nil {
return err
}
defer out.Close()

for _, obj := range objs {
yamlContent, err := yaml.Marshal(obj)
yamlContent, err := yamlMarshal(obj, options...)
if err != nil {
return err
}
Expand All @@ -147,6 +160,41 @@ func (g GenerationContext) WriteYAML(itemPath string, objs ...interface{}) error
return nil
}

// yamlMarshal is based on sigs.k8s.io/yaml.Marshal, but allows for transforming the final data before writing.
func yamlMarshal(o interface{}, options ...*WriteYAMLOptions) ([]byte, error) {
j, err := json.Marshal(o)
if err != nil {
return nil, fmt.Errorf("error marshaling into JSON: %v", err)
}

return yamlJSONToYAMLWithFilter(j, options...)
}

// yamlJSONToYAMLWithFilter is based on sigs.k8s.io/yaml.JSONToYAML, but allows for transforming the final data before writing.
func yamlJSONToYAMLWithFilter(j []byte, options ...*WriteYAMLOptions) ([]byte, error) {
// Convert the JSON to an object.
var jsonObj map[string]interface{}
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
// Go JSON library doesn't try to pick the right number type (int, float,
// etc.) when unmarshalling to interface{}, it just picks float64
// universally. go-yaml does go through the effort of picking the right
// number type, so we can preserve number type throughout this process.
if err := rawyaml.Unmarshal(j, &jsonObj); err != nil {
return nil, err
}

for _, option := range options {
if option.transform != nil {
if err := option.transform(jsonObj); err != nil {
return nil, err
}
}
}

// Marshal this object into YAML.
return rawyaml.Marshal(jsonObj)
}

// ReadFile reads the given boilerplate artifact using the context's InputRule.
func (g GenerationContext) ReadFile(path string) ([]byte, error) {
file, err := g.OpenForRead(path)
Expand Down
2 changes: 1 addition & 1 deletion pkg/rbac/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,5 +263,5 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
return nil
}

return ctx.WriteYAML("role.yaml", objs...)
return ctx.WriteYAML("role.yaml", objs)
}
2 changes: 1 addition & 1 deletion pkg/webhook/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ func (Generator) Generate(ctx *genall.GenerationContext) error {
} else {
fileName = fmt.Sprintf("manifests.%s.yaml", k)
}
if err := ctx.WriteYAML(fileName, v...); err != nil {
if err := ctx.WriteYAML(fileName, v); err != nil {
return err
}
}
Expand Down