From ca6228b526145d77b72aaf8e92a974f57288444d Mon Sep 17 00:00:00 2001 From: Nestor Date: Wed, 8 May 2019 15:21:47 +0200 Subject: [PATCH 1/2] add remove resource subcommand --- pkg/commands/edit/all.go | 2 + pkg/commands/edit/remove/all.go | 41 +++++ pkg/commands/edit/remove/removeresource.go | 122 +++++++++++++ .../edit/remove/removeresource_test.go | 171 ++++++++++++++++++ 4 files changed, 336 insertions(+) create mode 100644 pkg/commands/edit/remove/all.go create mode 100644 pkg/commands/edit/remove/removeresource.go create mode 100644 pkg/commands/edit/remove/removeresource_test.go diff --git a/pkg/commands/edit/all.go b/pkg/commands/edit/all.go index 7f94e35ed6..1b9e76b7ee 100644 --- a/pkg/commands/edit/all.go +++ b/pkg/commands/edit/all.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/kustomize/pkg/commands/edit/add" "sigs.k8s.io/kustomize/pkg/commands/edit/fix" + "sigs.k8s.io/kustomize/pkg/commands/edit/remove" "sigs.k8s.io/kustomize/pkg/commands/edit/set" "sigs.k8s.io/kustomize/pkg/fs" "sigs.k8s.io/kustomize/pkg/ifc" @@ -47,6 +48,7 @@ func NewCmdEdit(fsys fs.FileSystem, v ifc.Validator, kf ifc.KunstructuredFactory add.NewCmdAdd(fsys, v, kf), set.NewCmdSet(fsys, v), fix.NewCmdFix(fsys), + remove.NewCmdRemove(fsys), ) return c } diff --git a/pkg/commands/edit/remove/all.go b/pkg/commands/edit/remove/all.go new file mode 100644 index 0000000000..771eace4b6 --- /dev/null +++ b/pkg/commands/edit/remove/all.go @@ -0,0 +1,41 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remove + +import ( + "github.com/spf13/cobra" + "sigs.k8s.io/kustomize/pkg/fs" +) + +// NewCmdRemove returns an instance of 'remove' subcommand. +func NewCmdRemove(fsys fs.FileSystem) *cobra.Command { + c := &cobra.Command{ + Use: "remove", + Short: "Removes items to the kustomization file.", + Long: "", + Example: ` + # Removes resources to the kustomization file + kustomize edit remove resource {filepath} {filepath} + kustomize edit remove resource {pattern} +`, + Args: cobra.MinimumNArgs(1), + } + c.AddCommand( + newCmdRemoveResource(fsys), + ) + return c +} diff --git a/pkg/commands/edit/remove/removeresource.go b/pkg/commands/edit/remove/removeresource.go new file mode 100644 index 0000000000..08565ad0b1 --- /dev/null +++ b/pkg/commands/edit/remove/removeresource.go @@ -0,0 +1,122 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remove + +import ( + "errors" + "path/filepath" + + "github.com/spf13/cobra" + "sigs.k8s.io/kustomize/pkg/commands/kustfile" + "sigs.k8s.io/kustomize/pkg/fs" +) + +type removeResourceOptions struct { + resourceFilePaths []string +} + +// newCmdRemoveResource remove the name of a file containing a resource to the kustomization file. +func newCmdRemoveResource(fsys fs.FileSystem) *cobra.Command { + var o removeResourceOptions + + cmd := &cobra.Command{ + Use: "resource", + Short: "Remove resource file paths to the kustomization file.", + Example: ` + remove resource my-resource.yml + remove resource resource1.yml resource2.yml resource3.yml + remove resource resources/*.yml + `, + RunE: func(cmd *cobra.Command, args []string) error { + err := o.Validate(args) + if err != nil { + return err + } + err = o.Complete(cmd, args) + if err != nil { + return err + } + return o.RunRemoveResource(fsys) + }, + } + return cmd +} + +// Validate validates removeResource command. +func (o *removeResourceOptions) Validate(args []string) error { + if len(args) == 0 { + return errors.New("must specify a resource file") + } + o.resourceFilePaths = args + return nil +} + +// Complete completes removeResource command. +func (o *removeResourceOptions) Complete(cmd *cobra.Command, args []string) error { + return nil +} + +// RunRemoveResource runs Resource command (do real work). +func (o *removeResourceOptions) RunRemoveResource(fSys fs.FileSystem) error { + + mf, err := kustfile.NewKustomizationFile(fSys) + if err != nil { + return err + } + + m, err := mf.Read() + if err != nil { + return err + } + + resources, err := globPatterns(m.Resources, o.resourceFilePaths) + if err != nil { + return err + } + + if len(resources) == 0 { + return nil + } + + newResources := make([]string, 0, len(m.Resources)) + for _, resource := range m.Resources { + if kustfile.StringInSlice(resource, resources) { + continue + } + newResources = append(newResources, resource) + } + + m.Resources = newResources + return mf.Write(m) +} + +func globPatterns(resources []string, patterns []string) ([]string, error) { + var result []string + for _, pattern := range patterns { + for _, resource := range resources { + match, err := filepath.Match(pattern, resource) + if err != nil { + return nil, err + } + if !match { + continue + } + result = append(result, resource) + } + } + return result, nil +} diff --git a/pkg/commands/edit/remove/removeresource_test.go b/pkg/commands/edit/remove/removeresource_test.go new file mode 100644 index 0000000000..8ce014cccc --- /dev/null +++ b/pkg/commands/edit/remove/removeresource_test.go @@ -0,0 +1,171 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remove + +import ( + "errors" + "fmt" + "strings" + "testing" + + "sigs.k8s.io/kustomize/pkg/fs" +) + +func TestRemoveResources(t *testing.T) { + type given struct { + resources []string + removeArgs []string + } + type expected struct { + resources []string + deleted []string + err error + } + testCases := []struct { + description string + given given + expected expected + }{ + { + description: "remove resource", + given: given{ + resources: []string{ + "resource1.yaml", + "resource2.yaml", + "resource3.yaml", + }, + removeArgs: []string{"resource1.yaml"}, + }, + expected: expected{ + resources: []string{ + "resource2.yaml", + "resource3.yaml", + }, + deleted: []string{ + "resource1.yaml", + }, + }, + }, + { + description: "remove resources with pattern", + given: given{ + resources: []string{ + "foo/resource1.yaml", + "foo/resource2.yaml", + "foo/resource3.yaml", + "do/not/deleteme/please.yaml", + }, + removeArgs: []string{"foo/resource*.yaml"}, + }, + expected: expected{ + resources: []string{ + "do/not/deleteme/please.yaml", + }, + deleted: []string{ + "foo/resource1.yaml", + "foo/resource2.yaml", + "foo/resource3.yaml", + }, + }, + }, + { + description: "nothing found to remove", + given: given{ + resources: []string{ + "resource1.yaml", + "resource2.yaml", + "resource3.yaml", + }, + removeArgs: []string{"foo"}, + }, + expected: expected{ + resources: []string{ + "resource2.yaml", + "resource3.yaml", + "resource1.yaml", + }, + }, + }, + { + description: "no arguments", + given: given{}, + expected: expected{ + err: errors.New("must specify a resource file"), + }, + }, + { + description: "remove with multiple pattern arguments", + given: given{ + resources: []string{ + "foo/foo.yaml", + "bar/bar.yaml", + "resource3.yaml", + "do/not/deleteme/please.yaml", + }, + removeArgs: []string{ + "foo/*.*", + "bar/*.*", + "res*.yaml", + }, + }, + expected: expected{ + resources: []string{ + "do/not/deleteme/please.yaml", + }, + deleted: []string{ + "foo/foo.yaml", + "bar/bar.yaml", + "resource3.yaml", + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + fakeFS := fs.MakeFakeFS() + fakeFS.WriteTestKustomizationWith([]byte(fmt.Sprintf("resources:\n - %s", strings.Join(tc.given.resources, "\n - ")))) + cmd := newCmdRemoveResource(fakeFS) + err := cmd.RunE(cmd, tc.given.removeArgs) + if err != nil && tc.expected.err == nil { + + t.Errorf("unexpected cmd error: %v", err) + } else if tc.expected.err != nil { + if err.Error() != tc.expected.err.Error() { + t.Errorf("expected error did not occurred. Expected: %v. Actual: %v", tc.expected.err, err) + } + return + } + content, err := fakeFS.ReadTestKustomization() + if err != nil { + t.Errorf("unexpected read error: %v", err) + } + + for _, resourceFileName := range tc.expected.resources { + if !strings.Contains(string(content), resourceFileName) { + t.Errorf("expected resource not found in kustomization file.\nResource: %s\nKustomization file:\n%s", resourceFileName, content) + } + } + for _, resourceFileName := range tc.expected.deleted { + if strings.Contains(string(content), resourceFileName) { + t.Errorf("expected deleted resource found in kustomization file. Resource: %s\nKustomization file:\n%s", resourceFileName, content) + } + } + + }) + } +} From fa4dc14c9783043c51bc23c1652c7f41dda23771 Mon Sep 17 00:00:00 2001 From: Jeff Regan Date: Mon, 13 May 2019 10:01:55 -0700 Subject: [PATCH 2/2] Update all.go --- pkg/commands/edit/remove/all.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/commands/edit/remove/all.go b/pkg/commands/edit/remove/all.go index 771eace4b6..aa75f72728 100644 --- a/pkg/commands/edit/remove/all.go +++ b/pkg/commands/edit/remove/all.go @@ -25,10 +25,10 @@ import ( func NewCmdRemove(fsys fs.FileSystem) *cobra.Command { c := &cobra.Command{ Use: "remove", - Short: "Removes items to the kustomization file.", + Short: "Removes items from the kustomization file.", Long: "", Example: ` - # Removes resources to the kustomization file + # Removes resources from the kustomization file kustomize edit remove resource {filepath} {filepath} kustomize edit remove resource {pattern} `,