mirror of
https://github.com/fluxcd/flux2.git
synced 2026-02-21 15:11:47 +00:00
Merge 8dce48ae06 into 0fe4449870
This commit is contained in:
commit
b7fa441162
11 changed files with 139 additions and 52 deletions
|
|
@ -111,30 +111,24 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var options []build.BuilderOptionFunc
|
||||||
var builder *build.Builder
|
var builder *build.Builder
|
||||||
|
|
||||||
|
options = append(options,
|
||||||
|
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
||||||
|
build.WithTimeout(rootArgs.timeout),
|
||||||
|
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
||||||
|
build.WithIgnore(buildKsArgs.ignorePaths),
|
||||||
|
build.WithStrictSubstitute(buildKsArgs.strictSubst),
|
||||||
|
build.WithRecursive(buildKsArgs.recursive),
|
||||||
|
build.WithLocalSources(buildKsArgs.localSources),
|
||||||
|
)
|
||||||
|
|
||||||
if buildKsArgs.dryRun {
|
if buildKsArgs.dryRun {
|
||||||
builder, err = build.NewBuilder(name, buildKsArgs.path,
|
options = append(options, build.WithDryRun(buildKsArgs.dryRun))
|
||||||
build.WithTimeout(rootArgs.timeout),
|
|
||||||
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
|
||||||
build.WithDryRun(buildKsArgs.dryRun),
|
|
||||||
build.WithNamespace(*kubeconfigArgs.Namespace),
|
|
||||||
build.WithIgnore(buildKsArgs.ignorePaths),
|
|
||||||
build.WithStrictSubstitute(buildKsArgs.strictSubst),
|
|
||||||
build.WithRecursive(buildKsArgs.recursive),
|
|
||||||
build.WithLocalSources(buildKsArgs.localSources),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
builder, err = build.NewBuilder(name, buildKsArgs.path,
|
|
||||||
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
|
||||||
build.WithTimeout(rootArgs.timeout),
|
|
||||||
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
|
||||||
build.WithIgnore(buildKsArgs.ignorePaths),
|
|
||||||
build.WithStrictSubstitute(buildKsArgs.strictSubst),
|
|
||||||
build.WithRecursive(buildKsArgs.recursive),
|
|
||||||
build.WithLocalSources(buildKsArgs.localSources),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder, err = build.NewBuilder(name, buildKsArgs.path, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ func setup(t *testing.T, tmpl map[string]string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-source.yaml", tmpl, t)
|
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-source.yaml", tmpl, t)
|
||||||
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-kustomization.yaml", tmpl, t)
|
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-kustomization.yaml", tmpl, t)
|
||||||
|
testEnv.CreateObjectFile("./testdata/build-kustomization/sops-age.yaml", tmpl, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildKustomization(t *testing.T) {
|
func TestBuildKustomization(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ type diffKsFlags struct {
|
||||||
progressBar bool
|
progressBar bool
|
||||||
strictSubst bool
|
strictSubst bool
|
||||||
recursive bool
|
recursive bool
|
||||||
|
decryptSecrets bool
|
||||||
localSources map[string]string
|
localSources map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,6 +75,7 @@ func init() {
|
||||||
diffKsCmd.Flags().BoolVar(&diffKsArgs.strictSubst, "strict-substitute", false,
|
diffKsCmd.Flags().BoolVar(&diffKsArgs.strictSubst, "strict-substitute", false,
|
||||||
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
|
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
|
||||||
diffKsCmd.Flags().BoolVarP(&diffKsArgs.recursive, "recursive", "r", false, "Recursively diff Kustomizations")
|
diffKsCmd.Flags().BoolVarP(&diffKsArgs.recursive, "recursive", "r", false, "Recursively diff Kustomizations")
|
||||||
|
diffKsCmd.Flags().BoolVar(&diffKsArgs.decryptSecrets, "decrypt-secrets", false, "Decrypt SOPS-encrypted secrets for comparison")
|
||||||
diffKsCmd.Flags().StringToStringVar(&diffKsArgs.localSources, "local-sources", nil, "Comma-separated list of repositories in format: Kind/namespace/name=path")
|
diffKsCmd.Flags().StringToStringVar(&diffKsArgs.localSources, "local-sources", nil, "Comma-separated list of repositories in format: Kind/namespace/name=path")
|
||||||
diffCmd.AddCommand(diffKsCmd)
|
diffCmd.AddCommand(diffKsCmd)
|
||||||
}
|
}
|
||||||
|
|
@ -99,34 +101,28 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
options []build.BuilderOptionFunc
|
||||||
builder *build.Builder
|
builder *build.Builder
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
options = append(options,
|
||||||
|
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
||||||
|
build.WithTimeout(rootArgs.timeout),
|
||||||
|
build.WithKustomizationFile(diffKsArgs.kustomizationFile),
|
||||||
|
build.WithIgnore(diffKsArgs.ignorePaths),
|
||||||
|
build.WithStrictSubstitute(diffKsArgs.strictSubst),
|
||||||
|
build.WithRecursive(diffKsArgs.recursive),
|
||||||
|
build.WithDecryptSecrets(diffKsArgs.decryptSecrets),
|
||||||
|
build.WithLocalSources(diffKsArgs.localSources),
|
||||||
|
build.WithSingleKustomization(),
|
||||||
|
)
|
||||||
|
|
||||||
if diffKsArgs.progressBar {
|
if diffKsArgs.progressBar {
|
||||||
builder, err = build.NewBuilder(name, diffKsArgs.path,
|
options = append(options, build.WithProgressBar())
|
||||||
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
|
||||||
build.WithTimeout(rootArgs.timeout),
|
|
||||||
build.WithKustomizationFile(diffKsArgs.kustomizationFile),
|
|
||||||
build.WithProgressBar(),
|
|
||||||
build.WithIgnore(diffKsArgs.ignorePaths),
|
|
||||||
build.WithStrictSubstitute(diffKsArgs.strictSubst),
|
|
||||||
build.WithRecursive(diffKsArgs.recursive),
|
|
||||||
build.WithLocalSources(diffKsArgs.localSources),
|
|
||||||
build.WithSingleKustomization(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
builder, err = build.NewBuilder(name, diffKsArgs.path,
|
|
||||||
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
|
||||||
build.WithTimeout(rootArgs.timeout),
|
|
||||||
build.WithKustomizationFile(diffKsArgs.kustomizationFile),
|
|
||||||
build.WithIgnore(diffKsArgs.ignorePaths),
|
|
||||||
build.WithStrictSubstitute(diffKsArgs.strictSubst),
|
|
||||||
build.WithRecursive(diffKsArgs.recursive),
|
|
||||||
build.WithLocalSources(diffKsArgs.localSources),
|
|
||||||
build.WithSingleKustomization(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder, err = build.NewBuilder(name, diffKsArgs.path, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &RequestError{StatusCode: 2, Err: err}
|
return &RequestError{StatusCode: 2, Err: err}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,12 @@ func TestDiffKustomization(t *testing.T) {
|
||||||
objectFile: "./testdata/diff-kustomization/value-sops-secret.yaml",
|
objectFile: "./testdata/diff-kustomization/value-sops-secret.yaml",
|
||||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-drifted-value-sops-secret.golden"),
|
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-drifted-value-sops-secret.golden"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "diff with a drifted value in decrypted sops secret object",
|
||||||
|
args: "diff kustomization podinfo --path ./testdata/build-kustomization/decrypt-secret --progress-bar=false --decrypt-secrets",
|
||||||
|
objectFile: "./testdata/diff-kustomization/value-sops-secret.yaml",
|
||||||
|
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-decryption.golden"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "diff with a sops dockerconfigjson secret object",
|
name: "diff with a sops dockerconfigjson secret object",
|
||||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false",
|
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false",
|
||||||
|
|
|
||||||
|
|
@ -435,7 +435,9 @@ func resetCmdArgs() {
|
||||||
checkArgs = checkFlags{}
|
checkArgs = checkFlags{}
|
||||||
createArgs = createFlags{}
|
createArgs = createFlags{}
|
||||||
deleteArgs = deleteFlags{}
|
deleteArgs = deleteFlags{}
|
||||||
diffKsArgs = diffKsFlags{}
|
diffKsArgs = diffKsFlags{
|
||||||
|
localSources: map[string]string{},
|
||||||
|
}
|
||||||
exportArgs = exportFlags{}
|
exportArgs = exportFlags{}
|
||||||
getArgs = GetFlags{}
|
getArgs = GetFlags{}
|
||||||
gitArgs = gitFlags{}
|
gitArgs = gitFlags{}
|
||||||
|
|
|
||||||
27
cmd/flux/testdata/build-kustomization/decrypt-secret/podinfo-token-sops-secret.yaml
vendored
Normal file
27
cmd/flux/testdata/build-kustomization/decrypt-secret/podinfo-token-sops-secret.yaml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: podinfo-token-77t89m9b67
|
||||||
|
stringData:
|
||||||
|
token: ENC[AES256_GCM,data:ut7THDa7SJMTIn26orb2,iv:jBqKk4f8jzOZLpoH7pMnryHRAwwvjaycKwBryEBO3oQ=,tag:193UGSrkhQJzs4pDg5u2mQ==,type:str]
|
||||||
|
type: Opaque
|
||||||
|
sops:
|
||||||
|
kms: []
|
||||||
|
gcp_kms: []
|
||||||
|
azure_kv: []
|
||||||
|
hc_vault: []
|
||||||
|
age:
|
||||||
|
- recipient: age1yqval9atdcnzjwhmutcjwdukfe5pk9tsa3lqya90u08grp03zgyss93knx
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxeGdXSVAyMGUzSFpwRGNF
|
||||||
|
bUV5bU9scVJsRUVwbERFYWVjSVpJNFlYREJRCm5xaGxzZGRic0ZwY3hJSmJOcWk3
|
||||||
|
UmYzUDNIU29zd3orYlFlemNGUDhWZVEKLS0tIFJCcEsrdmlZcHBFWFE3SUlCaUNZ
|
||||||
|
ZkJuMm83a0VNODdXMkxUeDRmemJ2blkKebY+krevnla3Rxhrm3T4mmao8NUishwl
|
||||||
|
W4sV4fM2m5gjpiz72MVPjUrakqo9lA9ZLUkSue95YzFe09o7uqglRQ==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2025-02-16T20:34:53Z"
|
||||||
|
mac: ENC[AES256_GCM,data:C6Sv7iAoMztDGMDTYEW5KFUGSdey6O9zLzNdaEHxQL1oTrQB/hSBOjA4jaEBHovdCL/58w9jDTq8G30IGqUEFEu4HM0YUrSDA1gdTrbtvOfza0hQC8CtmCBWgol3tsWBwcLAeFOlE95perdvKkJx10t/r8yb8biCpLtJcxa/WZE=,iv:2CswtWAATMPZ7BHzWSUNhvT9xfmSSGPdOMvG1jHi3Nk=,tag:FZeCX+EuAlsOGaZbErpfJQ==,type:str]
|
||||||
|
pgp: []
|
||||||
|
encrypted_regex: ^(data|stringData)$
|
||||||
|
version: 3.9.1
|
||||||
|
|
@ -13,6 +13,10 @@ spec:
|
||||||
kind: GitRepository
|
kind: GitRepository
|
||||||
name: podinfo
|
name: podinfo
|
||||||
targetNamespace: default
|
targetNamespace: default
|
||||||
|
decryption:
|
||||||
|
provider: sops
|
||||||
|
secretRef:
|
||||||
|
name: sops-age
|
||||||
postBuild:
|
postBuild:
|
||||||
substitute:
|
substitute:
|
||||||
cluster_env: "prod"
|
cluster_env: "prod"
|
||||||
|
|
|
||||||
10
cmd/flux/testdata/build-kustomization/sops-age.yaml
vendored
Normal file
10
cmd/flux/testdata/build-kustomization/sops-age.yaml
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: sops-age
|
||||||
|
namespace: {{ .fluxns }}
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
identity.agekey: |
|
||||||
|
# public key: age1yqval9atdcnzjwhmutcjwdukfe5pk9tsa3lqya90u08grp03zgyss93knx
|
||||||
|
AGE-SECRET-KEY-1JYSQLQ4QM6GZHDF4F5JLA3HZD2DFJFCMAA2ASCN2USTC02KC4V6SSZNLA7
|
||||||
7
cmd/flux/testdata/diff-kustomization/diff-with-decryption.golden
vendored
Normal file
7
cmd/flux/testdata/diff-kustomization/diff-with-decryption.golden
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
► Secret/default/podinfo-token-77t89m9b67 drifted
|
||||||
|
|
||||||
|
data.token
|
||||||
|
± value change
|
||||||
|
- *** (before)
|
||||||
|
+ *** (after)
|
||||||
|
|
||||||
|
|
@ -44,6 +44,7 @@ import (
|
||||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||||
|
|
||||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
||||||
|
"github.com/fluxcd/kustomize-controller/decryptor"
|
||||||
"github.com/fluxcd/pkg/kustomize"
|
"github.com/fluxcd/pkg/kustomize"
|
||||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||||
ssautil "github.com/fluxcd/pkg/ssa/utils"
|
ssautil "github.com/fluxcd/pkg/ssa/utils"
|
||||||
|
|
@ -77,15 +78,16 @@ type Builder struct {
|
||||||
kustomizationFile string
|
kustomizationFile string
|
||||||
ignore []string
|
ignore []string
|
||||||
// mu is used to synchronize access to the kustomization file
|
// mu is used to synchronize access to the kustomization file
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
action kustomize.Action
|
action kustomize.Action
|
||||||
kustomization *kustomizev1.Kustomization
|
kustomization *kustomizev1.Kustomization
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
spinner *yacspin.Spinner
|
spinner *yacspin.Spinner
|
||||||
dryRun bool
|
dryRun bool
|
||||||
strictSubst bool
|
strictSubst bool
|
||||||
recursive bool
|
recursive bool
|
||||||
localSources map[string]string
|
decryptSecrets bool
|
||||||
|
localSources map[string]string
|
||||||
// diff needs to handle kustomizations one by one
|
// diff needs to handle kustomizations one by one
|
||||||
singleKustomization bool
|
singleKustomization bool
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +192,14 @@ func WithRecursive(recursive bool) BuilderOptionFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithDecryptSecrets sets the decrypt secrets field
|
||||||
|
func WithDecryptSecrets(decryptSecrets bool) BuilderOptionFunc {
|
||||||
|
return func(b *Builder) error {
|
||||||
|
b.decryptSecrets = decryptSecrets
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithLocalSources sets the local sources field
|
// WithLocalSources sets the local sources field
|
||||||
func WithLocalSources(localSources map[string]string) BuilderOptionFunc {
|
func WithLocalSources(localSources map[string]string) BuilderOptionFunc {
|
||||||
return func(b *Builder) error {
|
return func(b *Builder) error {
|
||||||
|
|
@ -520,7 +530,36 @@ func (b *Builder) do(ctx context.Context, kustomization kustomizev1.Kustomizatio
|
||||||
return nil, fmt.Errorf("kustomize build failed: %w", err)
|
return nil, fmt.Errorf("kustomize build failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dec *decryptor.Decryptor
|
||||||
|
var cleanup func()
|
||||||
|
if b.decryptSecrets {
|
||||||
|
dec, cleanup, err = decryptor.NewTempDecryptor(b.resourcesPath, b.client, b.kustomization)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
// Import decryption keys
|
||||||
|
if err := dec.ImportKeys(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, res := range m.Resources() {
|
for _, res := range m.Resources() {
|
||||||
|
if res.GetKind() == "Secret" && b.decryptSecrets {
|
||||||
|
outRes, err := dec.DecryptResource(res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decryption failed for '%s': %w", res.GetName(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if outRes != nil {
|
||||||
|
_, err = m.Replace(res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// run variable substitutions
|
// run variable substitutions
|
||||||
if kustomization.Spec.PostBuild != nil {
|
if kustomization.Spec.PostBuild != nil {
|
||||||
data, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&kustomization)
|
data, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&kustomization)
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,7 @@ func (b *Builder) kustomizationDiff(kustomization *kustomizev1.Kustomization) (s
|
||||||
WithIgnore(b.ignore),
|
WithIgnore(b.ignore),
|
||||||
WithStrictSubstitute(b.strictSubst),
|
WithStrictSubstitute(b.strictSubst),
|
||||||
WithRecursive(b.recursive),
|
WithRecursive(b.recursive),
|
||||||
|
WithDecryptSecrets(b.decryptSecrets),
|
||||||
WithLocalSources(b.localSources),
|
WithLocalSources(b.localSources),
|
||||||
WithSingleKustomization(),
|
WithSingleKustomization(),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue