Skip to content

Commit 92e862c

Browse files
authored
Merge pull request #5544 from sanaasy/sanaasy/add-no-verify-flag
Run kustomize build with kustomize localize and add a no-verify flag.
2 parents cb432b0 + 8db4c4b commit 92e862c

File tree

2 files changed

+134
-8
lines changed

2 files changed

+134
-8
lines changed

kustomize/commands/localize/localize.go

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
package localize
55

66
import (
7+
"bytes"
78
"log"
9+
"path/filepath"
810

911
"github.com/spf13/cobra"
1012
lclzr "sigs.k8s.io/kustomize/api/krusty/localizer"
13+
"sigs.k8s.io/kustomize/kustomize/v5/commands/build"
14+
"sigs.k8s.io/kustomize/kyaml/copyutil"
1115
"sigs.k8s.io/kustomize/kyaml/errors"
1216
"sigs.k8s.io/kustomize/kyaml/filesys"
1317
)
@@ -20,23 +24,26 @@ type arguments struct {
2024
}
2125

2226
type flags struct {
23-
scope string
27+
scope string
28+
noVerify bool
2429
}
2530

2631
// NewCmdLocalize returns a new localize command.
2732
func NewCmdLocalize(fs filesys.FileSystem) *cobra.Command {
2833
var f flags
34+
var buildBuffer bytes.Buffer
35+
buildCmd := build.NewCmdBuild(fs, &build.Help{}, &buildBuffer)
2936
cmd := &cobra.Command{
3037
Use: "localize [target [destination]]",
3138
Short: "[Alpha] Creates localized copy of target kustomization root at destination",
32-
Long: `[Alpha] Creates copy of target kustomization directory or
33-
versioned URL at destination, where remote references in the original
39+
Long: `[Alpha] Creates copy of target kustomization directory or
40+
versioned URL at destination, where remote references in the original
3441
are replaced by local references to the downloaded remote content.
3542
36-
If target is not specified, the current working directory will be used.
37-
Destination is a path to a new directory in an existing directory. If
38-
destination is not specified, a new directory will be created in the current
39-
working directory.
43+
If target is not specified, the current working directory will be used.
44+
Destination is a path to a new directory in an existing directory. If
45+
destination is not specified, a new directory will be created in the current
46+
working directory.
4047
4148
For details, see: https://kubectl.docs.kubernetes.io/references/kustomize/cmd/
4249
@@ -46,7 +53,7 @@ alphabetizes kustomization fields in the localized copy.
4653
`,
4754
Example: `
4855
# Localize the current working directory, with default scope and destination
49-
kustomize localize
56+
kustomize localize
5057
5158
# Localize some local directory, with scope and default destination
5259
kustomize localize /home/path/scope/target --scope /home/path/scope
@@ -62,6 +69,30 @@ kustomize localize https://github.com/kubernetes-sigs/kustomize//api/krusty/test
6269
if err != nil {
6370
return errors.Wrap(err)
6471
}
72+
73+
if !f.noVerify {
74+
originalBuild, err := runBuildCmd(buildBuffer, buildCmd, args.target)
75+
if err != nil {
76+
return errors.Wrap(err)
77+
}
78+
79+
buildDst := dst
80+
if f.scope != "" && f.scope != args.target {
81+
buildDst = filepath.Join(dst, filepath.Base(args.target))
82+
}
83+
84+
localizedBuild, err := runBuildCmd(buildBuffer, buildCmd, buildDst)
85+
if err != nil {
86+
return errors.Wrap(err)
87+
}
88+
89+
if localizedBuild != originalBuild {
90+
copyutil.PrettyFileDiff(originalBuild, localizedBuild)
91+
log.Fatalf("VERIFICATION FAILED: `kustomize build` for %s and %s are different after localization.\n", args.target, dst)
92+
}
93+
log.Printf("VERIFICATION SUCCESS: `kustomize build` for %s and %s are the same after localization.\n", args.target, dst)
94+
}
95+
6596
log.Printf("SUCCESS: localized %q to directory %s\n", args.target, dst)
6697
return nil
6798
},
@@ -74,6 +105,12 @@ kustomize localize https://github.com/kubernetes-sigs/kustomize//api/krusty/test
74105
Cannot specify for remote targets, as scope is by default the containing repo.
75106
If not specified for local target, scope defaults to target.
76107
`)
108+
cmd.Flags().BoolVar(&f.noVerify,
109+
"no-verify",
110+
false,
111+
`Does not verify that the outputs of kustomize build for target and newDir are the same after localization.
112+
If not specified, this flag defaults to false and will run kustomize build.
113+
`)
77114
return cmd
78115
}
79116

@@ -92,3 +129,16 @@ func matchArgs(rawArgs []string) arguments {
92129
}
93130
return args
94131
}
132+
133+
func runBuildCmd(buffer bytes.Buffer, cmd *cobra.Command, folder string) (buildOutput string, err error) {
134+
buffer.Reset()
135+
buildErr := cmd.RunE(cmd, []string{folder})
136+
if buildErr != nil {
137+
log.Printf("If your target directory requires flags to build: \n"+
138+
"1. Add executable permissions for the downloaded exec binaries in '%s'. \n"+
139+
"2. Run kustomize build with the necessary flags and self-verify the outputs.", folder)
140+
return "", errors.Wrap(buildErr)
141+
}
142+
143+
return buffer.String(), nil
144+
}

kustomize/commands/localize/localize_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,24 @@ spec:
3939
- containerPort: 80
4040
`
4141

42+
const helmKustomization = `apiVersion: kustomize.config.k8s.io/v1beta1
43+
kind: Kustomization
44+
helmCharts:
45+
- name: external-dns
46+
repo: oci://registry-1.docker.io/bitnamicharts
47+
version: 6.19.2
48+
releaseName: test
49+
valuesInline:
50+
crd:
51+
create: false
52+
rbac:
53+
create: false
54+
serviceAccount:
55+
create: false
56+
service:
57+
enabled: false
58+
`
59+
4260
func TestScopeFlag(t *testing.T) {
4361
kustomizations := map[string]string{
4462
filepath.Join("target", "kustomization.yaml"): fmt.Sprintf(`resources:
@@ -66,6 +84,60 @@ func TestScopeFlag(t *testing.T) {
6684
loctest.CheckFs(t, testDir.String(), expected, actual)
6785
}
6886

87+
func TestNoVerifyFlag(t *testing.T) {
88+
kustomization := map[string]string{
89+
"kustomization.yaml": `resources:
90+
- deployment.yaml
91+
`,
92+
"deployment.yaml": deployment,
93+
}
94+
expected, actual, target := loctest.PrepareFs(t, nil, kustomization)
95+
96+
buffy := new(bytes.Buffer)
97+
log.SetOutput(buffy)
98+
defer func() {
99+
log.SetOutput(os.Stderr)
100+
}()
101+
cmd := localize.NewCmdLocalize(actual)
102+
require.NoError(t, cmd.Flags().Set("no-verify", "true"))
103+
err := cmd.RunE(cmd, []string{
104+
target.String(),
105+
target.Join("dst"),
106+
})
107+
require.NoError(t, err)
108+
109+
loctest.SetupDir(t, expected, target.Join("dst"), kustomization)
110+
loctest.CheckFs(t, target.String(), expected, actual)
111+
112+
successMsg := fmt.Sprintf(`SUCCESS: localized "%s" to directory %s
113+
`, target.String(), target.Join("dst"))
114+
verifyMsg := "VERIFICATION"
115+
require.NotContains(t, buffy.String(), verifyMsg)
116+
require.Contains(t, buffy.String(), successMsg)
117+
}
118+
119+
func TestFailingBuildCmd(t *testing.T) {
120+
kustomization := map[string]string{
121+
"kustomization.yaml": helmKustomization,
122+
}
123+
_, actual, target := loctest.PrepareFs(t, nil, kustomization)
124+
125+
buffy := new(bytes.Buffer)
126+
log.SetOutput(buffy)
127+
defer func() {
128+
log.SetOutput(os.Stderr)
129+
}()
130+
cmd := localize.NewCmdLocalize(actual)
131+
err := cmd.RunE(cmd, []string{
132+
target.String(),
133+
target.Join("dst"),
134+
})
135+
require.Error(t, err)
136+
137+
verifyMsg := "If your target directory requires flags to build"
138+
require.Contains(t, buffy.String(), verifyMsg)
139+
}
140+
69141
func TestOptionalArgs(t *testing.T) {
70142
for name, args := range map[string][]string{
71143
"no_target": {},
@@ -99,6 +171,8 @@ func TestOptionalArgs(t *testing.T) {
99171
loctest.SetupDir(t, expected, dst, kust)
100172
loctest.CheckFs(t, testDir.String(), expected, actual)
101173

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

205+
verifyMsg := "VERIFICATION SUCCESS"
206+
require.Contains(t, buffy.String(), verifyMsg)
131207
successMsg := fmt.Sprintf(`SUCCESS: localized "%s" to directory %s
132208
`, target.String(), target.Join("dst"))
133209
require.Contains(t, buffy.String(), successMsg)

0 commit comments

Comments
 (0)