Skip to content

Commit

Permalink
Merge pull request #5544 from sanaasy/sanaasy/add-no-verify-flag
Browse files Browse the repository at this point in the history
Run kustomize build with kustomize localize and add a no-verify flag.
  • Loading branch information
k8s-ci-robot authored Jun 5, 2024
2 parents cb432b0 + 8db4c4b commit 92e862c
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 8 deletions.
66 changes: 58 additions & 8 deletions kustomize/commands/localize/localize.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
package localize

import (
"bytes"
"log"
"path/filepath"

"github.com/spf13/cobra"
lclzr "sigs.k8s.io/kustomize/api/krusty/localizer"
"sigs.k8s.io/kustomize/kustomize/v5/commands/build"
"sigs.k8s.io/kustomize/kyaml/copyutil"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
Expand All @@ -20,23 +24,26 @@ type arguments struct {
}

type flags struct {
scope string
scope string
noVerify bool
}

// NewCmdLocalize returns a new localize command.
func NewCmdLocalize(fs filesys.FileSystem) *cobra.Command {
var f flags
var buildBuffer bytes.Buffer
buildCmd := build.NewCmdBuild(fs, &build.Help{}, &buildBuffer)
cmd := &cobra.Command{
Use: "localize [target [destination]]",
Short: "[Alpha] Creates localized copy of target kustomization root at destination",
Long: `[Alpha] Creates copy of target kustomization directory or
versioned URL at destination, where remote references in the original
Long: `[Alpha] Creates copy of target kustomization directory or
versioned URL at destination, where remote references in the original
are replaced by local references to the downloaded remote content.
If target is not specified, the current working directory will be used.
Destination is a path to a new directory in an existing directory. If
destination is not specified, a new directory will be created in the current
working directory.
If target is not specified, the current working directory will be used.
Destination is a path to a new directory in an existing directory. If
destination is not specified, a new directory will be created in the current
working directory.
For details, see: https://kubectl.docs.kubernetes.io/references/kustomize/cmd/
Expand All @@ -46,7 +53,7 @@ alphabetizes kustomization fields in the localized copy.
`,
Example: `
# Localize the current working directory, with default scope and destination
kustomize localize
kustomize localize
# Localize some local directory, with scope and default destination
kustomize localize /home/path/scope/target --scope /home/path/scope
Expand All @@ -62,6 +69,30 @@ kustomize localize https://github.com/kubernetes-sigs/kustomize//api/krusty/test
if err != nil {
return errors.Wrap(err)
}

if !f.noVerify {
originalBuild, err := runBuildCmd(buildBuffer, buildCmd, args.target)
if err != nil {
return errors.Wrap(err)
}

buildDst := dst
if f.scope != "" && f.scope != args.target {
buildDst = filepath.Join(dst, filepath.Base(args.target))
}

localizedBuild, err := runBuildCmd(buildBuffer, buildCmd, buildDst)
if err != nil {
return errors.Wrap(err)
}

if localizedBuild != originalBuild {
copyutil.PrettyFileDiff(originalBuild, localizedBuild)
log.Fatalf("VERIFICATION FAILED: `kustomize build` for %s and %s are different after localization.\n", args.target, dst)
}
log.Printf("VERIFICATION SUCCESS: `kustomize build` for %s and %s are the same after localization.\n", args.target, dst)
}

log.Printf("SUCCESS: localized %q to directory %s\n", args.target, dst)
return nil
},
Expand All @@ -74,6 +105,12 @@ kustomize localize https://github.com/kubernetes-sigs/kustomize//api/krusty/test
Cannot specify for remote targets, as scope is by default the containing repo.
If not specified for local target, scope defaults to target.
`)
cmd.Flags().BoolVar(&f.noVerify,
"no-verify",
false,
`Does not verify that the outputs of kustomize build for target and newDir are the same after localization.
If not specified, this flag defaults to false and will run kustomize build.
`)
return cmd
}

Expand All @@ -92,3 +129,16 @@ func matchArgs(rawArgs []string) arguments {
}
return args
}

func runBuildCmd(buffer bytes.Buffer, cmd *cobra.Command, folder string) (buildOutput string, err error) {
buffer.Reset()
buildErr := cmd.RunE(cmd, []string{folder})
if buildErr != nil {
log.Printf("If your target directory requires flags to build: \n"+
"1. Add executable permissions for the downloaded exec binaries in '%s'. \n"+
"2. Run kustomize build with the necessary flags and self-verify the outputs.", folder)
return "", errors.Wrap(buildErr)
}

return buffer.String(), nil
}
76 changes: 76 additions & 0 deletions kustomize/commands/localize/localize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,24 @@ spec:
- containerPort: 80
`

const helmKustomization = `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
helmCharts:
- name: external-dns
repo: oci://registry-1.docker.io/bitnamicharts
version: 6.19.2
releaseName: test
valuesInline:
crd:
create: false
rbac:
create: false
serviceAccount:
create: false
service:
enabled: false
`

func TestScopeFlag(t *testing.T) {
kustomizations := map[string]string{
filepath.Join("target", "kustomization.yaml"): fmt.Sprintf(`resources:
Expand Down Expand Up @@ -66,6 +84,60 @@ func TestScopeFlag(t *testing.T) {
loctest.CheckFs(t, testDir.String(), expected, actual)
}

func TestNoVerifyFlag(t *testing.T) {
kustomization := map[string]string{
"kustomization.yaml": `resources:
- deployment.yaml
`,
"deployment.yaml": deployment,
}
expected, actual, target := loctest.PrepareFs(t, nil, kustomization)

buffy := new(bytes.Buffer)
log.SetOutput(buffy)
defer func() {
log.SetOutput(os.Stderr)
}()
cmd := localize.NewCmdLocalize(actual)
require.NoError(t, cmd.Flags().Set("no-verify", "true"))
err := cmd.RunE(cmd, []string{
target.String(),
target.Join("dst"),
})
require.NoError(t, err)

loctest.SetupDir(t, expected, target.Join("dst"), kustomization)
loctest.CheckFs(t, target.String(), expected, actual)

successMsg := fmt.Sprintf(`SUCCESS: localized "%s" to directory %s
`, target.String(), target.Join("dst"))
verifyMsg := "VERIFICATION"
require.NotContains(t, buffy.String(), verifyMsg)
require.Contains(t, buffy.String(), successMsg)
}

func TestFailingBuildCmd(t *testing.T) {
kustomization := map[string]string{
"kustomization.yaml": helmKustomization,
}
_, actual, target := loctest.PrepareFs(t, nil, kustomization)

buffy := new(bytes.Buffer)
log.SetOutput(buffy)
defer func() {
log.SetOutput(os.Stderr)
}()
cmd := localize.NewCmdLocalize(actual)
err := cmd.RunE(cmd, []string{
target.String(),
target.Join("dst"),
})
require.Error(t, err)

verifyMsg := "If your target directory requires flags to build"
require.Contains(t, buffy.String(), verifyMsg)
}

func TestOptionalArgs(t *testing.T) {
for name, args := range map[string][]string{
"no_target": {},
Expand Down Expand Up @@ -99,6 +171,8 @@ func TestOptionalArgs(t *testing.T) {
loctest.SetupDir(t, expected, dst, kust)
loctest.CheckFs(t, testDir.String(), expected, actual)

verifyMsg := "VERIFICATION SUCCESS"
require.Contains(t, buffy.String(), verifyMsg)
successMsg := fmt.Sprintf(`SUCCESS: localized "." to directory %s
`, dst)
require.Contains(t, buffy.String(), successMsg)
Expand Down Expand Up @@ -128,6 +202,8 @@ func TestOutput(t *testing.T) {
loctest.SetupDir(t, expected, target.Join("dst"), kustomization)
loctest.CheckFs(t, target.String(), expected, actual)

verifyMsg := "VERIFICATION SUCCESS"
require.Contains(t, buffy.String(), verifyMsg)
successMsg := fmt.Sprintf(`SUCCESS: localized "%s" to directory %s
`, target.String(), target.Join("dst"))
require.Contains(t, buffy.String(), successMsg)
Expand Down

0 comments on commit 92e862c

Please sign in to comment.