mirror of
https://github.com/fluxcd/flux2.git
synced 2026-04-14 07:46:51 +00:00
Merge pull request #5845 from rycli/enable-diff-new-ks
Some checks are pending
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
scan / analyze (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
update / update-components (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
ossf / scorecard (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
Some checks are pending
conformance / conform-kubernetes (1.33.0) (push) Waiting to run
conformance / conform-kubernetes (1.34.1) (push) Waiting to run
conformance / conform-kubernetes (1.35.0) (push) Waiting to run
conformance / conform-k3s (1.33.7) (push) Waiting to run
scan / analyze (push) Waiting to run
conformance / conform-k3s (1.34.3) (push) Waiting to run
conformance / conform-openshift (4.20.0-okd) (push) Waiting to run
update / update-components (push) Waiting to run
conformance / conform-k3s (1.35.0) (push) Waiting to run
e2e-bootstrap / e2e-boostrap-github (push) Waiting to run
ossf / scorecard (push) Waiting to run
e2e / e2e-amd64-kubernetes (push) Waiting to run
Add `--ignore-not-found` to `flux diff ks`
This commit is contained in:
commit
7d27a26665
19 changed files with 251 additions and 5 deletions
|
|
@ -63,6 +63,7 @@ type diffKsFlags struct {
|
|||
recursive bool
|
||||
localSources map[string]string
|
||||
inMemoryBuild bool
|
||||
ignoreNotFound bool
|
||||
}
|
||||
|
||||
var diffKsArgs diffKsFlags
|
||||
|
|
@ -78,6 +79,8 @@ func init() {
|
|||
diffKsCmd.Flags().StringToStringVar(&diffKsArgs.localSources, "local-sources", nil, "Comma-separated list of repositories in format: Kind/namespace/name=path")
|
||||
diffKsCmd.Flags().BoolVar(&diffKsArgs.inMemoryBuild, "in-memory-build", true,
|
||||
"Use in-memory filesystem during build.")
|
||||
diffKsCmd.Flags().BoolVar(&diffKsArgs.ignoreNotFound, "ignore-not-found", false,
|
||||
"Ignore Kustomization not found errors on the cluster when diffing.")
|
||||
diffCmd.AddCommand(diffKsCmd)
|
||||
}
|
||||
|
||||
|
|
@ -117,6 +120,7 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
|||
build.WithLocalSources(diffKsArgs.localSources),
|
||||
build.WithSingleKustomization(),
|
||||
build.WithInMemoryBuild(diffKsArgs.inMemoryBuild),
|
||||
build.WithIgnoreNotFound(diffKsArgs.ignoreNotFound),
|
||||
)
|
||||
} else {
|
||||
builder, err = build.NewBuilder(name, diffKsArgs.path,
|
||||
|
|
@ -129,6 +133,7 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
|||
build.WithLocalSources(diffKsArgs.localSources),
|
||||
build.WithSingleKustomization(),
|
||||
build.WithInMemoryBuild(diffKsArgs.inMemoryBuild),
|
||||
build.WithIgnoreNotFound(diffKsArgs.ignoreNotFound),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ func TestDiffKustomization(t *testing.T) {
|
|||
name: "diff nothing deployed",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false",
|
||||
objectFile: "",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/nothing-is-deployed.golden"),
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-new-kustomization.golden"),
|
||||
},
|
||||
{
|
||||
name: "diff with a deployment object",
|
||||
|
|
@ -96,7 +96,7 @@ func TestDiffKustomization(t *testing.T) {
|
|||
name: "diff where kustomization file has multiple objects with the same name",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false --kustomization-file ./testdata/diff-kustomization/flux-kustomization-multiobj.yaml",
|
||||
objectFile: "",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/nothing-is-deployed.golden"),
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-new-kustomization.golden"),
|
||||
},
|
||||
{
|
||||
name: "diff with recursive",
|
||||
|
|
@ -138,6 +138,118 @@ func TestDiffKustomization(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestDiffKustomizationNotDeployed tests `flux diff ks` when the Kustomization
|
||||
// CR does not exist in the cluster but is provided via --kustomization-file.
|
||||
// Reproduces https://github.com/fluxcd/flux2/issues/5439
|
||||
func TestDiffKustomizationNotDeployed(t *testing.T) {
|
||||
// Use a dedicated namespace with NO setup() -- the Kustomization CR
|
||||
// intentionally does not exist in the cluster.
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
setupTestNamespace(tmpl["fluxns"], t)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
assert assertFunc
|
||||
}{
|
||||
{
|
||||
name: "fails without --ignore-not-found",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false " +
|
||||
"--kustomization-file ./testdata/diff-kustomization/flux-kustomization-local-only.yaml",
|
||||
assert: assertError("failed to get kustomization object: kustomizations.kustomize.toolkit.fluxcd.io \"podinfo\" not found"),
|
||||
},
|
||||
{
|
||||
name: "succeeds with --ignore-not-found and --kustomization-file",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false " +
|
||||
"--kustomization-file ./testdata/diff-kustomization/flux-kustomization-local-only.yaml " +
|
||||
"--ignore-not-found",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-new-kustomization.golden"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: tt.args + " -n " + tmpl["fluxns"],
|
||||
assert: tt.assert,
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestDiffKustomizationTakeOwnership tests `flux diff ks` when taking ownership
|
||||
// of existing resources on the cluster. A "pre-existing" configmap is applied
|
||||
// to the cluster, and the kustomization contains a matching configmap; the
|
||||
// diff should show the labels added by flux
|
||||
func TestDiffKustomizationTakeOwnership(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
setupTestNamespace(tmpl["fluxns"], t)
|
||||
|
||||
b, _ := build.NewBuilder("configmaps", "", build.WithClientConfig(kubeconfigArgs, kubeclientOptions))
|
||||
resourceManager, err := b.Manager()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Pre-create the "existing" configmap in the cluster without Flux labels
|
||||
if _, err := resourceManager.ApplyAll(context.Background(), createObjectFromFile("./testdata/diff-kustomization/existing-configmap.yaml", tmpl, t), ssa.DefaultApplyOptions()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := cmdTestCase{
|
||||
args: "diff kustomization configmaps --path ./testdata/build-kustomization/configmaps --progress-bar=false " +
|
||||
"--kustomization-file ./testdata/diff-kustomization/flux-kustomization-configmaps.yaml " +
|
||||
"--ignore-not-found" +
|
||||
" -n " + tmpl["fluxns"],
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-taking-ownership.golden"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
// TestDiffKustomizationNewNamespaceAndConfigmap runs `flux diff ks` when the
|
||||
// kustomization creates a new namespace and resources inside it. The server-side
|
||||
// dry-run cannot resolve resources in a namespace that doesn't exist yet,
|
||||
// consistent with `kubectl diff --server-side` behavior.
|
||||
func TestDiffKustomizationNewNamespaceAndConfigmap(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
setupTestNamespace(tmpl["fluxns"], t)
|
||||
|
||||
cmd := cmdTestCase{
|
||||
args: "diff kustomization new-namespace-and-configmap --path ./testdata/build-kustomization/new-namespace-and-configmap --progress-bar=false " +
|
||||
"--kustomization-file ./testdata/diff-kustomization/flux-kustomization-new-namespace-and-configmap.yaml " +
|
||||
"--ignore-not-found" +
|
||||
" -n " + tmpl["fluxns"],
|
||||
assert: assertError("ConfigMap/new-ns/app-config not found: namespaces \"new-ns\" not found"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
// TestDiffKustomizationNewNamespaceOnly runs `flux diff ks` when the
|
||||
// kustomization creates only a new namespace. The diff should show the
|
||||
// namespace as created.
|
||||
func TestDiffKustomizationNewNamespaceOnly(t *testing.T) {
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
setupTestNamespace(tmpl["fluxns"], t)
|
||||
|
||||
cmd := cmdTestCase{
|
||||
args: "diff kustomization new-namespace-only --path ./testdata/build-kustomization/new-namespace-only --progress-bar=false " +
|
||||
"--kustomization-file ./testdata/diff-kustomization/flux-kustomization-new-namespace-only.yaml " +
|
||||
"--ignore-not-found" +
|
||||
" -n " + tmpl["fluxns"],
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-new-namespace-only.golden"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func createObjectFromFile(objectFile string, templateValues map[string]string, t *testing.T) []*unstructured.Unstructured {
|
||||
buf, err := os.ReadFile(objectFile)
|
||||
if err != nil {
|
||||
|
|
|
|||
7
cmd/flux/testdata/build-kustomization/configmaps/existing.yaml
vendored
Normal file
7
cmd/flux/testdata/build-kustomization/configmaps/existing.yaml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: existing-config
|
||||
namespace: default
|
||||
data:
|
||||
key: value
|
||||
5
cmd/flux/testdata/build-kustomization/configmaps/kustomization.yaml
vendored
Normal file
5
cmd/flux/testdata/build-kustomization/configmaps/kustomization.yaml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./existing.yaml
|
||||
- ./new.yaml
|
||||
7
cmd/flux/testdata/build-kustomization/configmaps/new.yaml
vendored
Normal file
7
cmd/flux/testdata/build-kustomization/configmaps/new.yaml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: new-config
|
||||
namespace: default
|
||||
data:
|
||||
key: value
|
||||
7
cmd/flux/testdata/build-kustomization/new-namespace-and-configmap/configmap.yaml
vendored
Normal file
7
cmd/flux/testdata/build-kustomization/new-namespace-and-configmap/configmap.yaml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config
|
||||
namespace: new-ns
|
||||
data:
|
||||
key: value
|
||||
5
cmd/flux/testdata/build-kustomization/new-namespace-and-configmap/kustomization.yaml
vendored
Normal file
5
cmd/flux/testdata/build-kustomization/new-namespace-and-configmap/kustomization.yaml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./namespace.yaml
|
||||
- ./configmap.yaml
|
||||
4
cmd/flux/testdata/build-kustomization/new-namespace-and-configmap/namespace.yaml
vendored
Normal file
4
cmd/flux/testdata/build-kustomization/new-namespace-and-configmap/namespace.yaml
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: new-ns
|
||||
4
cmd/flux/testdata/build-kustomization/new-namespace-only/kustomization.yaml
vendored
Normal file
4
cmd/flux/testdata/build-kustomization/new-namespace-only/kustomization.yaml
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ./namespace.yaml
|
||||
4
cmd/flux/testdata/build-kustomization/new-namespace-only/namespace.yaml
vendored
Normal file
4
cmd/flux/testdata/build-kustomization/new-namespace-only/namespace.yaml
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: new-ns
|
||||
1
cmd/flux/testdata/diff-kustomization/diff-new-namespace-only.golden
vendored
Normal file
1
cmd/flux/testdata/diff-kustomization/diff-new-namespace-only.golden
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
► Namespace/new-ns created
|
||||
9
cmd/flux/testdata/diff-kustomization/diff-taking-ownership.golden
vendored
Normal file
9
cmd/flux/testdata/diff-kustomization/diff-taking-ownership.golden
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
► ConfigMap/default/existing-config drifted
|
||||
|
||||
metadata
|
||||
+ one map entry added:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: configmaps
|
||||
kustomize.toolkit.fluxcd.io/namespace:
|
||||
|
||||
► ConfigMap/default/new-config created
|
||||
7
cmd/flux/testdata/diff-kustomization/existing-configmap.yaml
vendored
Normal file
7
cmd/flux/testdata/diff-kustomization/existing-configmap.yaml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: existing-config
|
||||
namespace: default
|
||||
data:
|
||||
key: value
|
||||
14
cmd/flux/testdata/diff-kustomization/flux-kustomization-configmaps.yaml
vendored
Normal file
14
cmd/flux/testdata/diff-kustomization/flux-kustomization-configmaps.yaml
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: configmaps
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./kustomize
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: configmaps
|
||||
targetNamespace: default
|
||||
14
cmd/flux/testdata/diff-kustomization/flux-kustomization-local-only.yaml
vendored
Normal file
14
cmd/flux/testdata/diff-kustomization/flux-kustomization-local-only.yaml
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./kustomize
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
targetNamespace: default
|
||||
13
cmd/flux/testdata/diff-kustomization/flux-kustomization-new-namespace-and-configmap.yaml
vendored
Normal file
13
cmd/flux/testdata/diff-kustomization/flux-kustomization-new-namespace-and-configmap.yaml
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: new-namespace-and-configmap
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./kustomize
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: new-namespace-and-configmap
|
||||
13
cmd/flux/testdata/diff-kustomization/flux-kustomization-new-namespace-only.yaml
vendored
Normal file
13
cmd/flux/testdata/diff-kustomization/flux-kustomization-new-namespace-only.yaml
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: new-namespace-only
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./kustomize
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: new-namespace-only
|
||||
|
|
@ -146,8 +146,9 @@ type Builder struct {
|
|||
strictSubst bool
|
||||
recursive bool
|
||||
localSources map[string]string
|
||||
// diff needs to handle kustomizations one by one
|
||||
// diff needs to handle kustomizations one by one, and opt-in to ignore kustomizations missing on cluster
|
||||
singleKustomization bool
|
||||
ignoreNotFound bool
|
||||
fsBackend fsBackend
|
||||
}
|
||||
|
||||
|
|
@ -235,6 +236,15 @@ func WithStrictSubstitute(strictSubstitute bool) BuilderOptionFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// WithIgnoreNotFound ignores NotFound errors from the cluster kustomization
|
||||
// lookup as long as a local kustomization file is provided
|
||||
func WithIgnoreNotFound(ignore bool) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.ignoreNotFound = ignore
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithIgnore sets ignore field
|
||||
func WithIgnore(ignore []string) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
|
|
@ -345,6 +355,10 @@ func NewBuilder(name, resources string, opts ...BuilderOptionFunc) (*Builder, er
|
|||
return nil, fmt.Errorf("kustomization file is required for dry-run")
|
||||
}
|
||||
|
||||
if b.ignoreNotFound && b.kustomizationFile == "" {
|
||||
return nil, fmt.Errorf("kustomization file is required when assuming new kustomizations")
|
||||
}
|
||||
|
||||
if !b.dryRun && b.client == nil {
|
||||
return nil, fmt.Errorf("client is required for live run")
|
||||
}
|
||||
|
|
@ -443,10 +457,11 @@ func (b *Builder) build() (m resmap.ResMap, err error) {
|
|||
} else {
|
||||
liveKus, err = b.getKustomization(ctx)
|
||||
if err != nil {
|
||||
if !apierrors.IsNotFound(err) || b.kustomization == nil {
|
||||
unknownError := !apierrors.IsNotFound(err)
|
||||
hasLocalFallback := b.kustomization != nil || b.ignoreNotFound
|
||||
if unknownError || !hasLocalFallback {
|
||||
return nil, fmt.Errorf("failed to get kustomization object: %w", err)
|
||||
}
|
||||
// use provided Kustomization
|
||||
liveKus = b.kustomization
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue