diff --git a/pkg/commands/kustomizationfile.go b/pkg/commands/kustomizationfile.go index 0dcade479..2cc29074d 100644 --- a/pkg/commands/kustomizationfile.go +++ b/pkg/commands/kustomizationfile.go @@ -35,8 +35,23 @@ import ( ) var ( - kustomizationFields = []string{"resources", "bases", "namePrefix", "namespace", "crds", "commonLabels", "commonAnnotations", "patches", "configMapGenerator", "secretGenerator", "vars", "imageTags"} - recognizedFields = regexp.MustCompile("^(" + strings.Join(kustomizationFields, "|") + "):") + // These field names are the exact kustomization fields + kustomizationFields = []string{ + "APIVersion", + "Kind", + "Resources", + "Bases", + "NamePrefix", + "Namespace", + "Crds", + "CommonLabels", + "CommonAnnotations", + "Patches", + "ConfigMapGenerator", + "SecretGenerator", + "Vars", + "ImageTags", + } ) // commentedField records the comment associated with a kustomization field @@ -51,6 +66,10 @@ func (cf *commentedField) appendComment(comment []byte) { cf.comment = append(cf.comment, comment...) } +func squash(x [][]byte) []byte { + return bytes.Join(x, []byte(``)) +} + type kustomizationFile struct { path string fsys fs.FileSystem @@ -129,20 +148,20 @@ func stringInSlice(str string, list []string) bool { func (mf *kustomizationFile) parseCommentedFields(content []byte) error { buffer := bytes.NewBuffer(content) var comments [][]byte - var currentfield string line, err := buffer.ReadBytes('\n') for err == nil { if isCommentOrBlankLine(line) { comments = append(comments, line) - } else if recognizedFields.Match(line) { - fields := recognizedFields.FindSubmatch(line) - currentfield = string(fields[1]) - mf.originalFields = append(mf.originalFields, &commentedField{field: currentfield, comment: bytes.Join(comments, []byte(``))}) - comments = [][]byte{} - } else if len(comments) > 0 { - mf.originalFields[len(mf.originalFields)-1].appendComment(bytes.Join(comments, []byte(``))) - comments = [][]byte{} + } else { + matched, field := findMatchedField(line) + if matched { + mf.originalFields = append(mf.originalFields, &commentedField{field: field, comment: squash(comments)}) + comments = [][]byte{} + } else if len(comments) > 0 { + mf.originalFields[len(mf.originalFields)-1].appendComment(squash(comments)) + comments = [][]byte{} + } } line, err = buffer.ReadBytes('\n') } @@ -199,6 +218,17 @@ func isCommentOrBlankLine(line []byte) bool { return len(s) == 0 || bytes.HasPrefix(s, []byte(`#`)) } +func findMatchedField(line []byte) (bool, string) { + for _, field := range kustomizationFields { + // (?i) is for case insensitive regexp matching + r := regexp.MustCompile("^(" + "(?i)" + field + "):") + if r.Match(line) { + return true, field + } + } + return false, "" +} + // marshalField marshal a given field of a kustomization object into yaml format. // If the field wasn't in the original kustomization.yaml file or wasn't added, // an empty []byte is returned. diff --git a/pkg/commands/kustomizationfile_test.go b/pkg/commands/kustomizationfile_test.go index 4f447c416..2b145cb3d 100644 --- a/pkg/commands/kustomizationfile_test.go +++ b/pkg/commands/kustomizationfile_test.go @@ -147,6 +147,8 @@ resources: # See which field this comment goes into - service.yaml +APIVersion: v1beta1 +kind: kustomization.yaml # something you may want to keep vars: @@ -158,7 +160,7 @@ vars: kind: Service name: my-service -bases: +BASES: - ../namespaces # some descriptions for the patches @@ -180,6 +182,8 @@ resources: - pod.yaml - service.yaml +apiVersion: v1beta1 +kind: kustomization.yaml # something you may want to keep vars: diff --git a/pkg/types/kustomization.go b/pkg/types/kustomization.go index 45d2bc1d8..a21d9e78a 100644 --- a/pkg/types/kustomization.go +++ b/pkg/types/kustomization.go @@ -17,8 +17,14 @@ limitations under the License. // Package types holds struct definitions that should find a better home. package types +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + // Kustomization holds the information needed to generate customized k8s api resources. type Kustomization struct { + metav1.TypeMeta `json:",inline" yaml:",inline"` + // NamePrefix will prefix the names of all resources mentioned in the kustomization // file including generated configmaps and secrets. NamePrefix string `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`