Add create subcommand

This commit is contained in:
Richard Marshall
2019-07-29 21:49:32 -07:00
parent e904f612f3
commit 5dfa929906
6 changed files with 450 additions and 0 deletions

View File

@@ -0,0 +1,181 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package create
import (
"fmt"
"os"
"path/filepath"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/v3/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/commands/util"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
)
type createFlags struct {
resources []string
namespace string
annotations string
labels string
prefix string
suffix string
detectResources bool
detectRecursive bool
path string
}
// NewCmdCreate returns an instance of 'create' subcommand.
func NewCmdCreate(fSys fs.FileSystem) *cobra.Command {
opts := createFlags{path: "."}
c := &cobra.Command{
Use: "create",
Short: "Create a new kustomization in the current directory",
Long: "",
Example: `
# Create a new overlay from the base '../base".
kustomize create --resource ../base
# Create a new kustomization detecting resources in the current directory.
kustomize create --autodetect
# Create a new kustomization with multiple resources and fields set.
kustomize create --resource depoyment.yaml --resource service.yaml --namespace staging --nameprefix acme-
`,
RunE: func(cmd *cobra.Command, args []string) error {
return runCreate(opts, fSys)
},
}
c.Flags().StringSliceVar(
&opts.resources,
"resource",
[]string{},
"Name of a file containing a file to add to the kustomization file.")
c.Flags().StringVar(
&opts.namespace,
"namespace",
"",
"Set the value of the namespace field in the customization file.")
c.Flags().StringVar(
&opts.annotations,
"annotation",
"",
"Add one or more common annotations.")
c.Flags().StringVar(
&opts.labels,
"label",
"",
"Add one or more common labels.")
c.Flags().StringVar(
&opts.prefix,
"nameprefix",
"",
"Sets the value of the namePrefix field in the kustomization file.")
c.Flags().StringVar(
&opts.suffix,
"namesuffix",
"",
"Sets the value of the nameSuffix field in the kustomization file.")
c.Flags().BoolVar(
&opts.detectResources,
"autodetect",
false,
"Search for kubernetes resources in the current directory to be added to the kustomization file.")
c.Flags().BoolVar(
&opts.detectRecursive,
"recursive",
false,
"Enable recursive directory searching for resource auto-detection.")
return c
}
func runCreate(opts createFlags, fSys fs.FileSystem) error {
resources, err := util.GlobPatterns(fSys, opts.resources)
if err != nil {
return err
}
if _, err := kustfile.NewKustomizationFile(fSys); err == nil {
return fmt.Errorf("kustomization file already exists")
}
if opts.detectResources {
detected, err := detectResources(fSys, opts.path, opts.detectRecursive)
if err != nil {
return err
}
for _, resource := range detected {
if kustfile.StringInSlice(resource, resources) {
continue
}
resources = append(resources, resource)
}
}
f, err := fSys.Create("kustomization.yaml")
if err != nil {
return err
}
f.Close()
mf, err := kustfile.NewKustomizationFile(fSys)
if err != nil {
return err
}
m, err := mf.Read()
if err != nil {
return err
}
m.Resources = resources
m.Namespace = opts.namespace
m.NamePrefix = opts.prefix
m.NameSuffix = opts.suffix
annotations, err := util.ConvertToMap(opts.annotations, "annotation")
if err != nil {
return err
}
m.CommonAnnotations = annotations
labels, err := util.ConvertToMap(opts.labels, "label")
if err != nil {
return err
}
m.CommonLabels = labels
return mf.Write(m)
}
func detectResources(fSys fs.FileSystem, base string, recursive bool) ([]string, error) {
var paths []string
factory := kunstruct.NewKunstructuredFactoryImpl()
err := fSys.Walk(base, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == base {
return nil
}
if info.IsDir() {
if !recursive {
return filepath.SkipDir
}
// If a sub-directory contains an existing kustomization file add the
// directory as a resource and do not decend into it.
for _, kfilename := range pgmconfig.KustomizationFileNames {
if fSys.Exists(filepath.Join(path, kfilename)) {
paths = append(paths, path)
return filepath.SkipDir
}
}
return nil
}
fContents, err := fSys.ReadFile(path)
if err != nil {
return err
}
if _, err := factory.SliceFromBytes(fContents); err != nil {
return nil
}
paths = append(paths, path)
return nil
})
return paths, err
}