Merge pull request #1242 from taxpon/add-patch-remover

Add patch remover
This commit is contained in:
Jeff Regan
2019-06-25 09:51:44 -07:00
committed by GitHub
11 changed files with 365 additions and 43 deletions

View File

@@ -21,6 +21,7 @@ import (
"log"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/patch"
@@ -70,7 +71,7 @@ func (o *addPatchOptions) Complete(cmd *cobra.Command, args []string) error {
// RunAddPatch runs addPatch command (do real work).
func (o *addPatchOptions) RunAddPatch(fSys fs.FileSystem) error {
patches, err := globPatterns(fSys, o.patchFilePaths)
patches, err := util.GlobPatterns(fSys, o.patchFilePaths)
if err != nil {
return err
}

View File

@@ -21,6 +21,7 @@ import (
"log"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
@@ -69,7 +70,7 @@ func (o *addResourceOptions) Complete(cmd *cobra.Command, args []string) error {
// RunAddResource runs addResource command (do real work).
func (o *addResourceOptions) RunAddResource(fSys fs.FileSystem) error {
resources, err := globPatterns(fSys, o.resourceFilePaths)
resources, err := util.GlobPatterns(fSys, o.resourceFilePaths)
if err != nil {
return err
}

View File

@@ -20,6 +20,7 @@ import (
"fmt"
"strings"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
@@ -85,7 +86,7 @@ func (a *flagsAndArgs) ExpandFileSource(fSys fs.FileSystem) error {
} else {
patterns = append(patterns, s[0])
}
result, err := globPatterns(fSys, patterns)
result, err := util.GlobPatterns(fSys, patterns)
if err != nil {
return err
}

View File

@@ -1,39 +0,0 @@
/*
Copyright 2018 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 add
import (
"log"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func globPatterns(fsys fs.FileSystem, patterns []string) ([]string, error) {
var result []string
for _, pattern := range patterns {
files, err := fsys.Glob(pattern)
if err != nil {
return nil, err
}
if len(files) == 0 {
log.Printf("%s has no match", pattern)
continue
}
result = append(result, files...)
}
return result, nil
}

View File

@@ -35,6 +35,9 @@ func NewCmdRemove(
kustomize edit remove resource {filepath} {filepath}
kustomize edit remove resource {pattern}
# Removes one or more patches from the kustomization file
kustomize edit remove patch <filepath>
# Removes one or more commonLabels from the kustomization file
kustomize edit remove label {labelKey1},{labelKey2}
@@ -47,6 +50,7 @@ func NewCmdRemove(
newCmdRemoveResource(fsys),
newCmdRemoveLabel(fsys, ldr.Validator().MakeLabelNameValidator()),
newCmdRemoveAnnotation(fsys, ldr.Validator().MakeAnnotationNameValidator()),
newCmdRemovePatch(fsys),
)
return c
}

View File

@@ -0,0 +1,91 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package remove
import (
"log"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/v3/pkg/commands/edit/util"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/patch"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
)
type removePatchOptions struct {
patchFilePaths []string
}
// newCmdRemovePatch removes the name of a file containing a patch from the kustomization file.
func newCmdRemovePatch(fsys fs.FileSystem) *cobra.Command {
var o removePatchOptions
cmd := &cobra.Command{
Use: "patch",
Short: "Removes one or more patches from " + pgmconfig.KustomizationFileNames[0],
Example: `
remove patch {filepath}`,
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.RunRemovePatch(fsys)
},
}
return cmd
}
// Validate validates removePatch command.
func (o *removePatchOptions) Validate(args []string) error {
if len(args) == 0 {
return errors.New("must specify a patch file")
}
o.patchFilePaths = args
return nil
}
// Complete completes removePatch command.
func (o *removePatchOptions) Complete(cmd *cobra.Command, args []string) error {
return nil
}
// RunRemovePatch runs removePatch command (do real work).
func (o *removePatchOptions) RunRemovePatch(fSys fs.FileSystem) error {
patches, err := util.GlobPatterns(fSys, o.patchFilePaths)
if err != nil {
return err
}
if len(patches) == 0 {
return nil
}
mf, err := kustfile.NewKustomizationFile(fSys)
if err != nil {
return err
}
m, err := mf.Read()
if err != nil {
return err
}
var removePatches []string
for _, p := range patches {
if !patch.Exist(m.PatchesStrategicMerge, p) {
log.Printf("patch %s doesn't exist in kustomization file", p)
continue
}
removePatches = append(removePatches, p)
}
m.PatchesStrategicMerge = patch.Delete(m.PatchesStrategicMerge, removePatches...)
return mf.Write(m)
}

View File

@@ -0,0 +1,136 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package remove
import (
"fmt"
"strings"
"testing"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/patch"
)
const (
patchFileContent = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
`
)
func makeKustomizationPatchFS() fs.FileSystem {
fakeFS := fs.MakeFakeFS()
patches := []string{"patch1.yaml", "patch2.yaml"}
fakeFS.WriteTestKustomizationWith([]byte(
fmt.Sprintf("patchesStrategicMerge:\n - %s",
strings.Join(patches, "\n - "))))
for _, p := range patches {
fakeFS.WriteFile(p, []byte(patchFileContent))
}
fakeFS.WriteFile("patch3.yaml", []byte(patchFileContent))
return fakeFS
}
func TestRemovePatch(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch1.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range args {
if patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must be deleted", k)
}
}
}
func TestRemovePatchMultipleArgs(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch1.yaml", "patch2.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range args {
if patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must be deleted", k)
}
}
}
func TestRemovePatchGlob(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch*.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
if len(m.PatchesStrategicMerge) != 0 {
t.Errorf("all patch must be deleted")
}
}
func TestRemovePatchNotDefinedInKustomization(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch3.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range []string{"patch1.yaml", "patch2.yaml"} {
if !patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must exist", k)
}
}
}
func TestRemovePatchNotExist(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
args := []string{"patch4.yaml"}
err := cmd.RunE(cmd, args)
if err != nil {
t.Errorf("unexpected error %v", err)
}
m := readKustomizationFS(t, fakeFS)
for _, k := range []string{"patch1.yaml", "patch2.yaml"} {
if !patch.Exist(m.PatchesStrategicMerge, k) {
t.Errorf("%s must exist", k)
}
}
}
func TestRemovePatchNoArgs(t *testing.T) {
fakeFS := makeKustomizationPatchFS()
cmd := newCmdRemovePatch(fakeFS)
err := cmd.RunE(cmd, nil)
if err == nil {
t.Errorf("expected an error")
}
if err.Error() != "must specify a patch file" {
t.Errorf("incorrect error: %v", err.Error())
}
}

View File

@@ -19,6 +19,7 @@ package remove
import (
"errors"
"path/filepath"
"sigs.k8s.io/kustomize/v3/pkg/pgmconfig"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/v3/pkg/commands/kustfile"
@@ -35,7 +36,7 @@ func newCmdRemoveResource(fsys fs.FileSystem) *cobra.Command {
cmd := &cobra.Command{
Use: "resource",
Short: "Remove resource file paths to the kustomization file.",
Short: "Removes one or more resource file paths from " + pgmconfig.KustomizationFileNames[0],
Example: `
remove resource my-resource.yml
remove resource resource1.yml resource2.yml resource3.yml

View File

@@ -0,0 +1,26 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package util
import (
"log"
"sigs.k8s.io/kustomize/v3/pkg/fs"
)
func GlobPatterns(fsys fs.FileSystem, patterns []string) ([]string, error) {
var result []string
for _, pattern := range patterns {
files, err := fsys.Glob(pattern)
if err != nil {
return nil, err
}
if len(files) == 0 {
log.Printf("%s has no match", pattern)
continue
}
result = append(result, files...)
}
return result, nil
}

View File

@@ -35,3 +35,20 @@ func Exist(patches []types.PatchStrategicMerge, path string) bool {
}
return false
}
// Delete deletes patches from a PatchStrategicMerge slice
func Delete(patches []types.PatchStrategicMerge, paths ...string) []types.PatchStrategicMerge {
// Convert paths into PatchStrategicMerge slice
convertedPath := make([]types.PatchStrategicMerge, len(paths))
for i, p := range paths {
convertedPath[i] = types.PatchStrategicMerge(p)
}
filteredPatches := make([]types.PatchStrategicMerge, 0, len(patches))
for _, containedPatch := range patches {
if !Exist(convertedPath, string(containedPatch)) {
filteredPatches = append(filteredPatches, containedPatch)
}
}
return filteredPatches
}

View File

@@ -0,0 +1,83 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.
package patch
import (
"testing"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
func buildPatchStrategicMergeSlice(patchStrings []string) []types.PatchStrategicMerge {
var patches []types.PatchStrategicMerge
for _, patchString := range patchStrings {
patches = append(patches, types.PatchStrategicMerge(patchString))
}
return patches
}
func TestAppend(t *testing.T) {
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
patches := buildPatchStrategicMergeSlice(patchStrings)
patches = Append(patches, "patch3.yaml")
for i, k := range []string{"patch1.yaml", "patch2.yaml", "patch3.yaml"} {
if patches[i] != types.PatchStrategicMerge(k) {
t.Fatalf("patches[%d] must be %s, got %s", i, k, patches[i])
}
}
}
func TestExistTrue(t *testing.T) {
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
patches := buildPatchStrategicMergeSlice(patchStrings)
for _, patchString := range patchStrings {
if !Exist(patches, patchString) {
t.Fatalf("%s must exist", patchString)
}
}
}
func TestExistFalse(t *testing.T) {
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
patches := buildPatchStrategicMergeSlice(patchStrings)
for _, patchString := range []string{"invalid1.yaml", "invalid2.yaml"} {
if Exist(patches, patchString) {
t.Fatalf("%s must not exist", patchString)
}
}
}
func TestDelete(t *testing.T) {
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
patches := buildPatchStrategicMergeSlice(patchStrings)
patches = Delete(patches, "patch1.yaml")
if Exist(patches, "patch1.yaml") {
t.Fatalf("patch1.yaml should be deleted")
}
if !Exist(patches, "patch2.yaml") {
t.Fatalf("patch2.yaml should exist")
}
if len(patches) != 1 {
t.Fatalf("Length of slice must be 1: actual %d", len(patches))
}
}
func TestDeleteMultiple(t *testing.T) {
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
patches := buildPatchStrategicMergeSlice(patchStrings)
patches = Delete(patches, "patch2.yaml", "patch4.yaml", "patch1.yaml", "patch3.yaml")
for _, k := range patchStrings {
if Exist(patches, k) {
t.Fatalf("%s should be deleted", k)
}
}
}