1/* 2Copyright 2019 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package add 18 19import ( 20 "fmt" 21 22 "github.com/spf13/cobra" 23 "sigs.k8s.io/kustomize/pkg/commands/kustfile" 24 "sigs.k8s.io/kustomize/pkg/fs" 25 "sigs.k8s.io/kustomize/pkg/ifc" 26 "sigs.k8s.io/kustomize/pkg/loader" 27 "sigs.k8s.io/kustomize/pkg/types" 28) 29 30// newCmdAddSecret returns a new command. 31func newCmdAddSecret(fSys fs.FileSystem, kf ifc.KunstructuredFactory) *cobra.Command { 32 var flags flagsAndArgs 33 cmd := &cobra.Command{ 34 Use: "secret NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--type=Opaque|kubernetes.io/tls]", 35 Short: "Adds a secret to the kustomization file.", 36 Long: "", 37 Example: ` 38 # Adds a secret to the kustomization file (with a specified key) 39 kustomize edit add secret my-secret --from-file=my-key=file/path --from-literal=my-literal=12345 40 41 # Adds a secret to the kustomization file (key is the filename) 42 kustomize edit add secret my-secret --from-file=file/path 43 44 # Adds a secret from env-file 45 kustomize edit add secret my-secret --from-env-file=env/path.env 46`, 47 RunE: func(_ *cobra.Command, args []string) error { 48 err := flags.ExpandFileSource(fSys) 49 if err != nil { 50 return err 51 } 52 53 err = flags.Validate(args) 54 if err != nil { 55 return err 56 } 57 58 // Load the kustomization file. 59 mf, err := kustfile.NewKustomizationFile(fSys) 60 if err != nil { 61 return err 62 } 63 64 kustomization, err := mf.Read() 65 if err != nil { 66 return err 67 } 68 69 // Add the flagsAndArgs map to the kustomization file. 70 kf.Set(loader.NewFileLoaderAtCwd(fSys)) 71 err = addSecret(kustomization, flags, kf) 72 if err != nil { 73 return err 74 } 75 76 // Write out the kustomization file with added secret. 77 return mf.Write(kustomization) 78 }, 79 } 80 81 cmd.Flags().StringSliceVar( 82 &flags.FileSources, 83 "from-file", 84 []string{}, 85 "Key file can be specified using its file path, in which case file basename will be used as secret "+ 86 "key, or optionally with a key and file path, in which case the given key will be used. Specifying a "+ 87 "directory will iterate each named file in the directory whose basename is a valid secret key.") 88 cmd.Flags().StringArrayVar( 89 &flags.LiteralSources, 90 "from-literal", 91 []string{}, 92 "Specify a key and literal value to insert in secret (i.e. mykey=somevalue)") 93 cmd.Flags().StringVar( 94 &flags.EnvFileSource, 95 "from-env-file", 96 "", 97 "Specify the path to a file to read lines of key=val pairs to create a secret (i.e. a Docker .env file).") 98 cmd.Flags().StringVar( 99 &flags.Type, 100 "type", 101 "Opaque", 102 "Specify the secret type this can be 'Opaque' (default), or 'kubernetes.io/tls'") 103 104 return cmd 105} 106 107// addSecret adds a secret to a kustomization file. 108// Note: error may leave kustomization file in an undefined state. 109// Suggest passing a copy of kustomization file. 110func addSecret( 111 k *types.Kustomization, 112 flags flagsAndArgs, kf ifc.KunstructuredFactory) error { 113 secretArgs := makeSecretArgs(k, flags.Name, flags.Type) 114 err := mergeFlagsIntoSecretArgs(&secretArgs.DataSources, flags) 115 if err != nil { 116 return err 117 } 118 // Validate by trying to create corev1.secret. 119 _, err = kf.MakeSecret(secretArgs, k.GeneratorOptions) 120 if err != nil { 121 return err 122 } 123 return nil 124} 125 126func makeSecretArgs(m *types.Kustomization, name, secretType string) *types.SecretArgs { 127 for i, v := range m.SecretGenerator { 128 if name == v.Name { 129 return &m.SecretGenerator[i] 130 } 131 } 132 // secret not found, create new one and add it to the kustomization file. 133 secret := &types.SecretArgs{GeneratorArgs: types.GeneratorArgs{Name: name}, Type: secretType} 134 m.SecretGenerator = append(m.SecretGenerator, *secret) 135 return &m.SecretGenerator[len(m.SecretGenerator)-1] 136} 137 138func mergeFlagsIntoSecretArgs(src *types.DataSources, flags flagsAndArgs) error { 139 src.LiteralSources = append(src.LiteralSources, flags.LiteralSources...) 140 src.FileSources = append(src.FileSources, flags.FileSources...) 141 if src.EnvSource != "" && src.EnvSource != flags.EnvFileSource { 142 return fmt.Errorf("updating existing env source '%s' not allowed", src.EnvSource) 143 } 144 src.EnvSource = flags.EnvFileSource 145 return nil 146} 147