diff --git a/pkg/kinflate/commands/configmap.go b/pkg/kinflate/commands/configmap.go index 8b1adf466..c9ddc912f 100644 --- a/pkg/kinflate/commands/configmap.go +++ b/pkg/kinflate/commands/configmap.go @@ -17,8 +17,13 @@ limitations under the License. package commands import ( + "fmt" "io" + manifest "k8s.io/kubectl/pkg/apis/manifest/v1alpha1" + "k8s.io/kubectl/pkg/kinflate/configmapandsecret" + "k8s.io/kubectl/pkg/kinflate/constants" + kutil "k8s.io/kubectl/pkg/kinflate/util" "k8s.io/kubectl/pkg/kinflate/util/fs" "github.com/spf13/cobra" @@ -46,9 +51,21 @@ func NewCmdAddConfigMap(errOut io.Writer, fsys fs.FileSystem) *cobra.Command { return err } - // TODO(apelisse,droot): Do something with that config. + // Load in the manifest file. + loader := kutil.ManifestLoader{FS: fsys} + m, err := loader.Read(constants.KubeManifestFileName) + if err != nil { + return err + } - return nil + // Add the config map to the manifest. + err = addConfigMap(m, config) + if err != nil { + return err + } + + // Write out the manifest with added configmap. + return loader.Write(constants.KubeManifestFileName, m) }, } @@ -58,3 +75,46 @@ func NewCmdAddConfigMap(errOut io.Writer, fsys fs.FileSystem) *cobra.Command { return cmd } + +// addConfigMap updates a configmap within a manifest, using the data in config. +// Note: error may leave manifest in an undefined state. Suggest passing a copy +// of manifest. +func addConfigMap(m *manifest.Manifest, config dataConfig) error { + cm := getOrCreateConfigMap(m, config.Name) + + err := mergeData(&cm.DataSources, config) + if err != nil { + return err + } + + // Validate manifest's configmap by trying to create corev1.configmap. + _, _, err = configmapandsecret.MakeConfigmapAndGenerateName(*cm) + if err != nil { + return err + } + + return nil +} + +func getOrCreateConfigMap(m *manifest.Manifest, name string) *manifest.ConfigMap { + for i, v := range m.Configmaps { + if name == v.Name { + return &m.Configmaps[i] + } + } + // config map not found, create new one and add it to the manifest. + cm := &manifest.ConfigMap{Name: name} + m.Configmaps = append(m.Configmaps, *cm) + return &m.Configmaps[len(m.Configmaps)-1] +} + +func mergeData(src *manifest.DataSources, config dataConfig) error { + src.LiteralSources = append(src.LiteralSources, config.LiteralSources...) + src.FileSources = append(src.FileSources, config.FileSources...) + if src.EnvSource != "" && src.EnvSource != config.EnvFileSource { + return fmt.Errorf("updating existing env source '%s' not allowed.", src.EnvSource) + } + src.EnvSource = config.EnvFileSource + + return nil +} diff --git a/pkg/kinflate/commands/configmap_test.go b/pkg/kinflate/commands/configmap_test.go index 1a3adb8b3..0fce01850 100644 --- a/pkg/kinflate/commands/configmap_test.go +++ b/pkg/kinflate/commands/configmap_test.go @@ -19,6 +19,7 @@ package commands import ( "testing" + manifest "k8s.io/kubectl/pkg/apis/manifest/v1alpha1" "k8s.io/kubectl/pkg/kinflate/util/fs" ) @@ -27,3 +28,102 @@ func TestNewAddConfigMapIsNotNil(t *testing.T) { t.Fatal("NewCmdAddConfigMap shouldn't be nil") } } + +func TestGetOrCreateConfigMap(t *testing.T) { + cmName := "test-config-name" + + manifest := &manifest.Manifest{ + NamePrefix: "test-name-prefix", + } + + if len(manifest.Configmaps) != 0 { + t.Fatal("Initial manifest should not have any configmaps") + } + cm := getOrCreateConfigMap(manifest, cmName) + + if cm == nil { + t.Fatalf("ConfigMap should always be non-nil") + } + + if len(manifest.Configmaps) != 1 { + t.Fatalf("Manifest should have newly created configmap") + } + + if &manifest.Configmaps[len(manifest.Configmaps)-1] != cm { + t.Fatalf("Pointer address for newly inserted configmap should be same") + } + + existingCM := getOrCreateConfigMap(manifest, cmName) + + if existingCM != cm { + t.Fatalf("should have returned an existing cm with name: %v", cmName) + } + + if len(manifest.Configmaps) != 1 { + t.Fatalf("Should not insert configmap for an existing name: %v", cmName) + } +} + +func TestMergeData_LiteralSources(t *testing.T) { + ds := &manifest.DataSources{} + + err := mergeData(ds, dataConfig{LiteralSources: []string{"k1=v1"}}) + if err != nil { + t.Fatalf("Merge initial literal source should not return error") + } + + if len(ds.LiteralSources) != 1 { + t.Fatalf("Initial literal source should have been added") + } + + err = mergeData(ds, dataConfig{LiteralSources: []string{"k2=v2"}}) + if err != nil { + t.Fatalf("Merge second literal source should not return error") + } + + if len(ds.LiteralSources) != 2 { + t.Fatalf("Second literal source should have been added") + } +} + +func TestMergeData_FileSources(t *testing.T) { + ds := &manifest.DataSources{} + + err := mergeData(ds, dataConfig{FileSources: []string{"file1"}}) + if err != nil { + t.Fatalf("Merge initial file source should not return error") + } + + if len(ds.FileSources) != 1 { + t.Fatalf("Initial file source should have been added") + } + + err = mergeData(ds, dataConfig{FileSources: []string{"file2"}}) + if err != nil { + t.Fatalf("Merge second file source should not return error") + } + + if len(ds.FileSources) != 2 { + t.Fatalf("Second file source should have been added") + } +} + +func TestMergeData_EnvSource(t *testing.T) { + envFileName := "env1" + envFileName2 := "env2" + ds := &manifest.DataSources{} + + err := mergeData(ds, dataConfig{EnvFileSource: envFileName}) + if err != nil { + t.Fatalf("Merge initial env source should not return error") + } + + if ds.EnvSource != envFileName { + t.Fatalf("Initial env source filename should have been added") + } + + err = mergeData(ds, dataConfig{EnvFileSource: envFileName2}) + if err == nil { + t.Fatalf("Updating env source should return an error") + } +} diff --git a/pkg/kinflate/commands/data_config.go b/pkg/kinflate/commands/data_config.go index e48365ae4..9ee241b84 100644 --- a/pkg/kinflate/commands/data_config.go +++ b/pkg/kinflate/commands/data_config.go @@ -29,6 +29,7 @@ type dataConfig struct { // LiteralSources to derive the configMap/Secret from (optional) LiteralSources []string // EnvFileSource to derive the configMap/Secret from (optional) + // TODO: Rationalize this name with Generic.EnvSource EnvFileSource string } diff --git a/pkg/kinflate/util/manifestloader_test.go b/pkg/kinflate/util/manifestloader_test.go index 992a24004..2f0fe85c0 100644 --- a/pkg/kinflate/util/manifestloader_test.go +++ b/pkg/kinflate/util/manifestloader_test.go @@ -32,12 +32,12 @@ func TestManifestLoader(t *testing.T) { loader := kutil.ManifestLoader{FS: fs.MakeFakeFS()} if err := loader.Write("my-manifest.yaml", manifest); err != nil { - t.Fatalf("Couldn't write manifest file: ", err) + t.Fatalf("Couldn't write manifest file: %v\n", err) } readManifest, err := loader.Read("my-manifest.yaml") if err != nil { - t.Fatalf("Couldn't read manifest file: ", err) + t.Fatalf("Couldn't read manifest file: %v\n", err) } if !reflect.DeepEqual(manifest, readManifest) { t.Fatal("Read manifest is different from written manifest")