diff --git a/cmd/convert.go b/cmd/convert.go index 389ae09..f5ed53b 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -50,6 +50,7 @@ type convertCmd struct { version string depUp bool forceGen bool + comments bool username string password string @@ -133,6 +134,7 @@ func NewConvertCommand() *cobra.Command { f.BoolVar(&k.forceGen, "force", false, "convert chart even if the destination directory already exists") f.StringVar(&k.username, "username", "", "chart repository username") f.StringVar(&k.password, "password", "", "chart repository password") + f.BoolVar(&k.comments, "comments", true, "add default comments to kustomization.yaml file") // log to stderr by default, flag.Set("logtostderr", "true") @@ -257,7 +259,7 @@ func (k *convertCmd) run() error { // write to disk generator := generators.NewGenerator(k.forceGen) - err = generator.Render(k.destination, config, chartRequested.Metadata, resources) + err = generator.Render(k.destination, config, chartRequested.Metadata, resources, k.comments) if err != nil { return err } diff --git a/pkg/generators/comments.go b/pkg/generators/comments.go new file mode 100644 index 0000000..b24fc09 --- /dev/null +++ b/pkg/generators/comments.go @@ -0,0 +1,30 @@ +package generators + +var commentsMapping = map[string]string{ + "namespace": "# Adds namespace to all resources.", + "namePrefix": "# Value of this field is prepended to the\n" + + "# names of all resources", + "commonLabels": "# Labels to add to all resources and selectors.", + "commonAnnotations": "# Annotations (non-identifying metadata)\n" + + "# to add to all resources. Like labels,\n" + + "# these are key value pairs.", + "resources": "# List of resource files that kustomize reads, modifies\n" + + "# and emits as a YAML string", + "configMapGenerator": "# Each entry in this list results in the creation of\n" + + "# one ConfigMap resource (it's a generator of n maps).", + "secretGenerator": "# Each entry in this list results in the creation of\n" + + "# one Secret resource (it's a generator of n secrets).", + "generatorOptions": "# generatorOptions modify behavior of all ConfigMap\n" + + "# and Secret generators", + "patches": "# Each entry in this list should resolve to\n" + + "# a partial or complete resource definition file.", + "patchesJson6902": "# Each entry in this list should resolve to\n" + + "# a kubernetes object and a JSON patch that will be applied\n" + + "# to the object.", + "crds": "# Each entry in this list should be a relative path to\n" + + "# a file for custom resource definition(CRD).", + "vars": "# Vars are used to insert values from resources that cannot\n" + + "# be referenced otherwise.", + "imageTags": "# ImageTags modify the tags for images without\n" + + "# creating patches.", +} diff --git a/pkg/generators/generators.go b/pkg/generators/generators.go index 9512c4d..5a5640b 100644 --- a/pkg/generators/generators.go +++ b/pkg/generators/generators.go @@ -4,15 +4,12 @@ package generators import ( "bufio" "fmt" - "io/ioutil" "os" "path" "strings" "github.com/ContainerSolutions/helm-convert/pkg/types" "github.com/ContainerSolutions/helm-convert/pkg/utils" - "github.com/ghodss/yaml" - "github.com/golang/glog" "k8s.io/helm/pkg/proto/hapi/chart" ktypes "sigs.k8s.io/kustomize/pkg/types" ) @@ -36,7 +33,7 @@ func NewGenerator(force bool) *Generator { } // Render to disk the kustomization.yaml, Kube-descriptor.yaml and associated resources -func (g *Generator) Render(destination string, config *ktypes.Kustomization, metadata *chart.Metadata, resources *types.Resources) error { +func (g *Generator) Render(destination string, config *ktypes.Kustomization, metadata *chart.Metadata, resources *types.Resources, addConfigComments bool) error { var err error // chech if destination path already exist, prompt user to confirm override @@ -82,30 +79,14 @@ func (g *Generator) Render(destination string, config *ktypes.Kustomization, met return err } - // render Kube-descriptor.yaml - err = writeYamlFile(path.Join(destination, DefaultKubeDescriptorFilename), metadata) - if err != nil { - return err - } - - return nil -} - -// writeYamlFile write a given interface into yaml -func writeYamlFile(filePath string, data interface{}) error { - output, err := yaml.Marshal(data) + // format and write kustomization.yaml + err = writeAndFormatKustomizationConfig(path.Join(destination, DefaultKustomizationFilename), addConfigComments) if err != nil { return err } - return writeFile(filePath, output, 0644) -} - -// writeFile writes data to a file named by filename. -func writeFile(filePath string, data []byte, perm os.FileMode) error { - glog.V(4).Infof("Writing %s", filePath) - - err := ioutil.WriteFile(filePath, data, perm) + // render Kube-descriptor.yaml + err = writeYamlFile(path.Join(destination, DefaultKubeDescriptorFilename), metadata) if err != nil { return err } diff --git a/pkg/generators/utils.go b/pkg/generators/utils.go new file mode 100644 index 0000000..8cc78e1 --- /dev/null +++ b/pkg/generators/utils.go @@ -0,0 +1,78 @@ +package generators + +import ( + "bufio" + "io/ioutil" + "os" + "regexp" + "strings" + + "github.com/ghodss/yaml" + "github.com/golang/glog" +) + +// Pattern used to detect if a line contains a YAML key +var yamlKeyPattern = regexp.MustCompile("^[^ :]*:") + +// writeYamlFile write a given interface into yaml +func writeYamlFile(filePath string, data interface{}) error { + output, err := yaml.Marshal(data) + if err != nil { + return err + } + + return writeFile(filePath, output, 0644) +} + +// writeAndFormatKustomizationConfig adds line break and comments +func writeAndFormatKustomizationConfig(filePath string, comments bool) error { + glog.V(4).Infof("Formatting %s", filePath) + + file, err := os.Open(filePath) + if err != nil { + return err + } + + defer file.Close() + + var output []string + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + + // add line break before comment except for if this is the first line + if yamlKeyPattern.MatchString(line) && len(output) > 0 { + output = append(output, "") + } + + // add comments + if comments { + for key, value := range commentsMapping { + if strings.HasPrefix(line, key+":") { + output = append(output, value) + } + } + } + + output = append(output, line) + } + + if err := scanner.Err(); err != nil { + return err + } + + return writeFile(filePath, []byte(strings.Join(output, "\n")), 0644) +} + +// writeFile writes data to a file named by filename. +func writeFile(filePath string, data []byte, perm os.FileMode) error { + glog.V(4).Infof("Writing %s", filePath) + + err := ioutil.WriteFile(filePath, data, perm) + if err != nil { + return err + } + + return nil +}