Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
412db70773 | ||
|
|
a1bb6babed | ||
|
|
568c536c3c | ||
|
|
d7129d6b55 | ||
|
|
4a893b13f8 | ||
|
|
8c2983c958 | ||
|
|
a30ffdb176 | ||
|
|
7a306e69ab | ||
|
|
23c4c2f1aa | ||
|
|
aac07f03d8 | ||
|
|
f4418920fb | ||
|
|
7752206152 | ||
|
|
c950f8f817 | ||
|
|
9276345fe7 | ||
|
|
01f910e257 | ||
|
|
de5f00016b | ||
|
|
877729aca3 | ||
|
|
f65d87b191 | ||
|
|
3b1d706b05 | ||
|
|
b0552fa0de | ||
|
|
cbca583f4b | ||
|
|
a0520de7aa | ||
|
|
4602b72778 | ||
|
|
e69a6ed91a | ||
|
|
9d6a037935 | ||
|
|
41df03f600 | ||
|
|
ca92464ef6 | ||
|
|
2e9fd33ce5 | ||
|
|
cf3f729f98 | ||
|
|
8b444283e6 |
@@ -19,6 +19,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -51,6 +52,18 @@ func init() {
|
||||
createCmd.PersistentFlags().BoolVar(&createArgs.export, "export", false, "export in YAML format to stdout")
|
||||
createCmd.PersistentFlags().StringSliceVar(&createArgs.labels, "label", nil,
|
||||
"set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)")
|
||||
createCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
if !validateObjectName(name) {
|
||||
return fmt.Errorf("name '%s' is invalid, it should adhere to standard defined in RFC 1123, the name can only contain alphanumeric characters or '-'", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
rootCmd.AddCommand(createCmd)
|
||||
}
|
||||
|
||||
@@ -150,3 +163,8 @@ func parseLabels() (map[string]string, error) {
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func validateObjectName(name string) bool {
|
||||
r := regexp.MustCompile("^[a-z0-9]([a-z0-9\\-]){0,61}[a-z0-9]$")
|
||||
return r.MatchString(name)
|
||||
}
|
||||
|
||||
@@ -63,9 +63,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createAlertCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("Alert name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if alertArgs.providerRef == "" {
|
||||
|
||||
@@ -73,9 +73,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("Provider name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if alertProviderArgs.alertType == "" {
|
||||
|
||||
@@ -139,9 +139,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("HelmRelease name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if helmReleaseArgs.chart == "" {
|
||||
|
||||
@@ -84,9 +84,6 @@ func (obj imagePolicyAdapter) getObservedGeneration() int64 {
|
||||
}
|
||||
|
||||
func createImagePolicyRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("ImagePolicy name is required")
|
||||
}
|
||||
objectName := args[0]
|
||||
|
||||
if imagePolicyArgs.imageRef == "" {
|
||||
|
||||
@@ -83,9 +83,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createImageRepositoryRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("ImageRepository name is required")
|
||||
}
|
||||
objectName := args[0]
|
||||
|
||||
if imageRepoArgs.image == "" {
|
||||
|
||||
@@ -49,25 +49,40 @@ mentioned in YAMLs in a git repository.`,
|
||||
--push-branch=image-updates \
|
||||
--author-name=flux \
|
||||
--author-email=flux@example.com \
|
||||
--commit-template="{{range .Updated.Images}}{{println .}}{{end}}"`,
|
||||
--commit-template="{{range .Updated.Images}}{{println .}}{{end}}"
|
||||
|
||||
# Configure image updates for a Git repository in a different namespace
|
||||
flux create image update apps \
|
||||
--namespace=apps \
|
||||
--git-repo-ref=flux-system \
|
||||
--git-repo-namespace=flux-system \
|
||||
--git-repo-path="./clusters/my-cluster" \
|
||||
--checkout-branch=main \
|
||||
--push-branch=image-updates \
|
||||
--author-name=flux \
|
||||
--author-email=flux@example.com \
|
||||
--commit-template="{{range .Updated.Images}}{{println .}}{{end}}"
|
||||
`,
|
||||
RunE: createImageUpdateRun,
|
||||
}
|
||||
|
||||
type imageUpdateFlags struct {
|
||||
gitRepoRef string
|
||||
gitRepoPath string
|
||||
checkoutBranch string
|
||||
pushBranch string
|
||||
commitTemplate string
|
||||
authorName string
|
||||
authorEmail string
|
||||
gitRepoName string
|
||||
gitRepoNamespace string
|
||||
gitRepoPath string
|
||||
checkoutBranch string
|
||||
pushBranch string
|
||||
commitTemplate string
|
||||
authorName string
|
||||
authorEmail string
|
||||
}
|
||||
|
||||
var imageUpdateArgs = imageUpdateFlags{}
|
||||
|
||||
func init() {
|
||||
flags := createImageUpdateCmd.Flags()
|
||||
flags.StringVar(&imageUpdateArgs.gitRepoRef, "git-repo-ref", "", "the name of a GitRepository resource with details of the upstream Git repository")
|
||||
flags.StringVar(&imageUpdateArgs.gitRepoName, "git-repo-ref", "", "the name of a GitRepository resource with details of the upstream Git repository")
|
||||
flags.StringVar(&imageUpdateArgs.gitRepoNamespace, "git-repo-namespace", "", "the namespace of the GitRepository resource, defaults to the ImageUpdateAutomation namespace")
|
||||
flags.StringVar(&imageUpdateArgs.gitRepoPath, "git-repo-path", "", "path to the directory containing the manifests to be updated, defaults to the repository root")
|
||||
flags.StringVar(&imageUpdateArgs.checkoutBranch, "checkout-branch", "", "the branch to checkout")
|
||||
flags.StringVar(&imageUpdateArgs.pushBranch, "push-branch", "", "the branch to push commits to, defaults to the checkout branch if not specified")
|
||||
@@ -79,12 +94,9 @@ func init() {
|
||||
}
|
||||
|
||||
func createImageUpdateRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("ImageUpdateAutomation name is required")
|
||||
}
|
||||
objectName := args[0]
|
||||
|
||||
if imageUpdateArgs.gitRepoRef == "" {
|
||||
if imageUpdateArgs.gitRepoName == "" {
|
||||
return fmt.Errorf("a reference to a GitRepository is required (--git-repo-ref)")
|
||||
}
|
||||
|
||||
@@ -113,8 +125,9 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
|
||||
},
|
||||
Spec: autov1.ImageUpdateAutomationSpec{
|
||||
SourceRef: autov1.CrossNamespaceSourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: imageUpdateArgs.gitRepoRef,
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: imageUpdateArgs.gitRepoName,
|
||||
Namespace: imageUpdateArgs.gitRepoNamespace,
|
||||
},
|
||||
|
||||
GitSpec: &autov1.GitSpec{
|
||||
|
||||
@@ -119,9 +119,6 @@ func NewKustomizationFlags() kustomizationFlags {
|
||||
}
|
||||
|
||||
func createKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("Kustomization name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if kustomizationArgs.path == "" {
|
||||
|
||||
@@ -67,9 +67,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("Receiver name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if receiverArgs.receiverType == "" {
|
||||
|
||||
@@ -112,9 +112,6 @@ func NewSecretGitFlags() secretGitFlags {
|
||||
}
|
||||
|
||||
func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("secret name is required")
|
||||
}
|
||||
name := args[0]
|
||||
if secretGitArgs.url == "" {
|
||||
return fmt.Errorf("url is required")
|
||||
|
||||
@@ -13,7 +13,7 @@ func TestCreateGitSecret(t *testing.T) {
|
||||
{
|
||||
name: "no args",
|
||||
args: "create secret git",
|
||||
assert: assertError("secret name is required"),
|
||||
assert: assertError("name is required"),
|
||||
},
|
||||
{
|
||||
name: "basic secret",
|
||||
|
||||
@@ -18,7 +18,6 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -68,9 +67,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("secret name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
labels, err := parseLabels()
|
||||
|
||||
@@ -12,7 +12,7 @@ func TestCreateHelmSecret(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
args: "create secret helm",
|
||||
assert: assertError("secret name is required"),
|
||||
assert: assertError("name is required"),
|
||||
},
|
||||
{
|
||||
args: "create secret helm helm-secret --username=my-username --password=my-password --namespace=my-namespace --export",
|
||||
|
||||
@@ -18,7 +18,6 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
@@ -67,9 +66,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("secret name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
labels, err := parseLabels()
|
||||
|
||||
@@ -12,7 +12,7 @@ func TestCreateTlsSecretNoArgs(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
args: "create secret tls",
|
||||
assert: assertError("secret name is required"),
|
||||
assert: assertError("name is required"),
|
||||
},
|
||||
{
|
||||
args: "create secret tls certs --namespace=my-namespace --cert-file=./testdata/create_secret/tls/test-cert.pem --key-file=./testdata/create_secret/tls/test-key.pem --export",
|
||||
|
||||
@@ -93,9 +93,6 @@ func NewSourceBucketFlags() sourceBucketFlags {
|
||||
}
|
||||
|
||||
func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("Bucket source name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if sourceBucketArgs.name == "" {
|
||||
|
||||
@@ -150,9 +150,6 @@ func newSourceGitFlags() sourceGitFlags {
|
||||
}
|
||||
|
||||
func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("GitRepository source name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if sourceGitArgs.url == "" {
|
||||
|
||||
@@ -96,7 +96,7 @@ func TestCreateSourceGit(t *testing.T) {
|
||||
{
|
||||
"NoArgs",
|
||||
"create source git",
|
||||
assertError("GitRepository source name is required"),
|
||||
assertError("name is required"),
|
||||
nil,
|
||||
}, {
|
||||
"Succeeded",
|
||||
|
||||
@@ -91,9 +91,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("HelmRepository source name is required")
|
||||
}
|
||||
name := args[0]
|
||||
|
||||
if sourceHelmArgs.url == "" {
|
||||
|
||||
@@ -70,9 +70,6 @@ func init() {
|
||||
}
|
||||
|
||||
func createTenantCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("tenant name is required")
|
||||
}
|
||||
tenant := args[0]
|
||||
if err := validation.IsQualifiedName(tenant); len(err) > 0 {
|
||||
return fmt.Errorf("invalid tenant name '%s': %v", tenant, err)
|
||||
|
||||
55
cmd/flux/create_test.go
Normal file
55
cmd/flux/create_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
)
|
||||
|
||||
func Test_validateObjectName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
name: "flux-system",
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
name: "-flux-system",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
name: "-flux-system-",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
name: "third.first",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
name: "THirdfirst",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
name: "THirdfirst",
|
||||
valid: false,
|
||||
},
|
||||
{
|
||||
name: rand.String(63),
|
||||
valid: true,
|
||||
},
|
||||
{
|
||||
name: rand.String(64),
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
valid := validateObjectName(tt.name)
|
||||
if valid != tt.valid {
|
||||
t.Errorf("expected name %q to return %t for validateObjectName func but got %t",
|
||||
tt.name, tt.valid, valid)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,18 @@ func TestDiffKustomization(t *testing.T) {
|
||||
objectFile: "./testdata/diff-kustomization/value-sops-secret.yaml",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-drifted-value-sops-secret.golden"),
|
||||
},
|
||||
{
|
||||
name: "diff with a sops dockerconfigjson secret object",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo",
|
||||
objectFile: "./testdata/diff-kustomization/dockerconfigjson-sops-secret.yaml",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-dockerconfigjson-sops-secret.golden"),
|
||||
},
|
||||
{
|
||||
name: "diff with a sops stringdata secret object",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo",
|
||||
objectFile: "./testdata/diff-kustomization/stringdata-sops-secret.yaml",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-stringdata-sops-secret.golden"),
|
||||
},
|
||||
}
|
||||
|
||||
tmpl := map[string]string{
|
||||
|
||||
@@ -21,12 +21,12 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -153,12 +153,18 @@ func NewRootFlags() rootFlags {
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
logger.Failuref("%v", err)
|
||||
|
||||
if err, ok := err.(*RequestError); ok {
|
||||
if err.StatusCode == 1 {
|
||||
logger.Warningf("%v", err)
|
||||
} else {
|
||||
logger.Failuref("%v", err)
|
||||
}
|
||||
|
||||
os.Exit(err.StatusCode)
|
||||
}
|
||||
|
||||
logger.Failuref("%v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,31 @@ spec:
|
||||
type: ClusterIP
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
.dockerconfigjson: eyJtYXNrIjoiKipTT1BTKioifQ==
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: docker-secret
|
||||
namespace: default
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: secret-basic-auth-stringdata
|
||||
namespace: default
|
||||
stringData:
|
||||
password: KipTT1BTKio=
|
||||
username: KipTT1BTKio=
|
||||
type: kubernetes.io/basic-auth
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
token: KipTT1BTKio=
|
||||
kind: Secret
|
||||
|
||||
27
cmd/flux/testdata/build-kustomization/podinfo/dockerconfigjson-sops-secret.yaml
vendored
Normal file
27
cmd/flux/testdata/build-kustomization/podinfo/dockerconfigjson-sops-secret.yaml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
.dockerconfigjson: ENC[AES256_GCM,data:KHCFH3hNnc+PMfWLFEPjebf3W4z4WXbGFAANRZyZC+07z7wlrTALJM6rn8YslW4tMAWCoAYxblC5WRCszTy0h9rw0U/RGOv5H0qCgnNg/FILFUqhwo9pNfrUH+MEP4M9qxxbLKZwObpHUE7DUsKx1JYAxsI=,iv:q48lqUbUQD+0cbYcjNMZMJLRdGHi78ZmDhNAT2th9tg=,tag:QRI2SZZXQrAcdql3R5AH2g==,type:str]
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: docker-secret
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age10la2ge0wtvx3qr7datqf7rs4yngxszdal927fs9rukamr8u2pshsvtz7ce
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3eU1CTEJhVXZ4eEVYYkVV
|
||||
OU90TEcrR2pYckttN0pBanJoSUZWSW1RQXlRCkUydFJ3V1NZUTBuVFF0aC9GUEcw
|
||||
bUdhNjJWTkoyL1FUVi9Dc1dxUDBkM0UKLS0tIE1sQXkwcWdGaEFuY0RHQTVXM0J6
|
||||
dWpJcThEbW15V3dXYXpPZklBdW1Hd1kKoIAdmGNPrEctV8h1w8KuvQ5S+BGmgqN9
|
||||
MgpNmUhJjWhgcQpb5BRYpQesBOgU5TBGK7j58A6DMDKlSiYZsdQchQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-02-03T16:03:17Z"
|
||||
mac: ENC[AES256_GCM,data:AHdYSawajwgAFwlmDN1IPNmT9vWaYKzyVIra2d6sPcjTbZ8/p+VRSRpVm4XZFFsaNnW5AUJaouwXnKYDTmJDXKlr/rQcu9kXqsssQgdzcXaA6l5uJlgsnml8ba7J3OK+iEKMax23mwQEx2EUskCd9ENOwFDkunP02sxqDNOz20k=,iv:8F5OamHt3fAVorf6p+SoIrWoqkcATSGWVoM0EK87S4M=,tag:E1mxXnc7wWkEX5BxhpLtng==,type:str]
|
||||
pgp: []
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.1
|
||||
@@ -4,6 +4,8 @@ resources:
|
||||
- ./deployment.yaml
|
||||
- ./hpa.yaml
|
||||
- ./service.yaml
|
||||
- ./dockerconfigjson-sops-secret.yaml
|
||||
- ./stringdata-secret.yaml
|
||||
secretGenerator:
|
||||
- files:
|
||||
- token=token.encrypted
|
||||
|
||||
28
cmd/flux/testdata/build-kustomization/podinfo/stringdata-secret.yaml
vendored
Normal file
28
cmd/flux/testdata/build-kustomization/podinfo/stringdata-secret.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret-basic-auth-stringdata
|
||||
type: kubernetes.io/basic-auth
|
||||
stringData:
|
||||
username: ENC[AES256_GCM,data:uKiQR48=,iv:jh2lgyAVu7igJAgoJsnOGhjxFyvUAa9lvT21u3hhqpU=,tag:zXM2JEpk3ZEH7WfkcWXXkw==,type:str]
|
||||
password: ENC[AES256_GCM,data:PyhZmNhy929JGQ==,iv:PBqPaJmSw21+kn4gIlg5VdjLNZyf613z5RUTCesBoVw=,tag:Hjc7DsuUrtsz7PYPdNkL3g==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age10la2ge0wtvx3qr7datqf7rs4yngxszdal927fs9rukamr8u2pshsvtz7ce
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJd0xxbDZhYjVoZzY4YWhK
|
||||
d2NvMVgrSGRVUGhHRGg3R1FpVURnbmh1TDBzCjcwby85M3JaK09QVk0yZFNMb2NL
|
||||
c2NQZW5hS1FhYlBHU0VoUzBVYzZYUUUKLS0tIEdaNEw2Y0VjVHpZc3pyYUtLVmJk
|
||||
NmN3K2VLU0NiZ1d0VHBYbGlCM1lrNmMKeWz3yfFbMNE+ly21oLfc1XnDSPRmnlPP
|
||||
wIs8lk/qrzVZ45C9GdWnnPeGZZiia46Yop9TxseUS8gCjJ6KCxJCAg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-02-06T12:51:07Z"
|
||||
mac: ENC[AES256_GCM,data:jtdzwj19uxdxvnmXg1HkAkDA6XlKMJOYFy7uLI5t/t11LwGop5Yeo7a4nQEEELehRx9J7B6U6NiySxAxBxWx5uW5vI5c8+069VV6dkiCIefnYSzuoIhQafjlFl1/KvH7VEjIWfHYuXF09v9PEKXkxEHUYDpS3QqQ3ymHRRI08pU=, iv:xX3E7F+AM29Pm8G5oqxRfYu9E7tEBGIaHeCJYgrtFmc=,tag:MJPGusNvu05z939jg8PAwQ==,type:str]
|
||||
pgp: []
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.1
|
||||
@@ -1,4 +1,6 @@
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo created
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/podinfo-token-77t89m9b67 created
|
||||
► Secret/default/db-user-pass-bkbd782d2c created
|
||||
|
||||
6
cmd/flux/testdata/diff-kustomization/diff-with-dockerconfigjson-sops-secret.golden
vendored
Normal file
6
cmd/flux/testdata/diff-kustomization/diff-with-dockerconfigjson-sops-secret.golden
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
► Deployment/default/podinfo created
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/podinfo-token-77t89m9b67 created
|
||||
► Secret/default/db-user-pass-bkbd782d2c created
|
||||
@@ -1,6 +1,8 @@
|
||||
► Deployment/default/podinfo created
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo created
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/podinfo-token-77t89m9b67 drifted
|
||||
|
||||
data
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
► Deployment/default/podinfo created
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo created
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/podinfo-token-77t89m9b67 created
|
||||
► Secret/default/db-user-pass-bkbd782d2c drifted
|
||||
|
||||
|
||||
@@ -7,5 +7,7 @@ spec.ports.http.port
|
||||
- 9899
|
||||
+ 9898
|
||||
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/podinfo-token-77t89m9b67 created
|
||||
► Secret/default/db-user-pass-bkbd782d2c created
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
► Deployment/default/podinfo created
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo created
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/db-user-pass-bkbd782d2c created
|
||||
|
||||
6
cmd/flux/testdata/diff-kustomization/diff-with-stringdata-sops-secret.golden
vendored
Normal file
6
cmd/flux/testdata/diff-kustomization/diff-with-stringdata-sops-secret.golden
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
► Deployment/default/podinfo created
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo created
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/podinfo-token-77t89m9b67 created
|
||||
► Secret/default/db-user-pass-bkbd782d2c created
|
||||
11
cmd/flux/testdata/diff-kustomization/dockerconfigjson-sops-secret.yaml
vendored
Normal file
11
cmd/flux/testdata/diff-kustomization/dockerconfigjson-sops-secret.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
.dockerconfigjson: eyJtYXNrIjoiKipTT1BTKioifQ==
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: docker-secret
|
||||
namespace: default
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
@@ -1,5 +1,7 @@
|
||||
► Deployment/default/podinfo created
|
||||
► HorizontalPodAutoscaler/default/podinfo created
|
||||
► Service/default/podinfo created
|
||||
► Secret/default/docker-secret created
|
||||
► Secret/default/secret-basic-auth-stringdata created
|
||||
► Secret/default/podinfo-token-77t89m9b67 created
|
||||
► Secret/default/db-user-pass-bkbd782d2c created
|
||||
|
||||
12
cmd/flux/testdata/diff-kustomization/stringdata-sops-secret.yaml
vendored
Normal file
12
cmd/flux/testdata/diff-kustomization/stringdata-sops-secret.yaml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
labels:
|
||||
kustomize.toolkit.fluxcd.io/name: podinfo
|
||||
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
|
||||
name: secret-basic-auth-stringdata
|
||||
namespace: default
|
||||
stringData:
|
||||
password: KipTT1BTKio=
|
||||
username: KipTT1BTKio=
|
||||
type: kubernetes.io/basic-auth
|
||||
2
cmd/flux/testdata/export/git-repo.yaml
vendored
2
cmd/flux/testdata/export/git-repo.yaml
vendored
@@ -11,6 +11,6 @@ spec:
|
||||
branch: main
|
||||
secretRef:
|
||||
name: flux-system
|
||||
timeout: 20s
|
||||
timeout: 1m0s
|
||||
url: ssh://git@github.com/example/repo
|
||||
|
||||
|
||||
24
go.mod
24
go.mod
@@ -6,27 +6,27 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.1.0
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20211221144345-a4f6767435ab
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/fluxcd/go-git-providers v0.5.3
|
||||
github.com/fluxcd/helm-controller/api v0.16.0
|
||||
github.com/fluxcd/go-git-providers v0.5.4
|
||||
github.com/fluxcd/helm-controller/api v0.17.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.20.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.16.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.0
|
||||
github.com/fluxcd/notification-controller/api v0.21.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.21.0
|
||||
github.com/fluxcd/notification-controller/api v0.22.0
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.3.1 // indirect
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.2
|
||||
github.com/fluxcd/pkg/kustomize v0.0.2
|
||||
github.com/fluxcd/pkg/runtime v0.12.4
|
||||
github.com/fluxcd/pkg/ssa v0.12.0
|
||||
github.com/fluxcd/pkg/ssa v0.13.0
|
||||
github.com/fluxcd/pkg/ssh v0.3.1
|
||||
github.com/fluxcd/pkg/untar v0.0.5
|
||||
github.com/fluxcd/pkg/version v0.0.1
|
||||
github.com/fluxcd/source-controller/api v0.21.1
|
||||
github.com/fluxcd/source-controller/api v0.21.2
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/gonvenience/bunt v1.3.2
|
||||
github.com/gonvenience/ytbx v1.4.2
|
||||
github.com/google/go-cmp v0.5.6
|
||||
github.com/google/go-containerregistry v0.2.0
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
|
||||
github.com/homeport/dyff v1.4.6
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
@@ -35,6 +35,7 @@ require (
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/spf13/cobra v1.2.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/theckman/yacspin v0.13.12
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
k8s.io/api v0.23.1
|
||||
@@ -45,8 +46,8 @@ require (
|
||||
k8s.io/kubectl v0.23.1
|
||||
sigs.k8s.io/cli-utils v0.27.0
|
||||
sigs.k8s.io/controller-runtime v0.11.0
|
||||
sigs.k8s.io/kustomize/api v0.10.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.0
|
||||
sigs.k8s.io/kustomize/api v0.11.2
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.3
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
@@ -73,6 +74,7 @@ require (
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||
@@ -108,8 +110,9 @@ require (
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.7 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
@@ -122,6 +125,7 @@ require (
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday v1.5.2 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
|
||||
43
go.sum
43
go.sum
@@ -221,19 +221,21 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwC
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fluxcd/go-git-providers v0.5.3 h1:Sg5XH+aXb6mYwITtdE4yc4yLoyFW3aVZx33qWuQb9/Q=
|
||||
github.com/fluxcd/go-git-providers v0.5.3/go.mod h1:4jTHTmSx3rFGnG78KUVgFYeG6vWFnKwUSr2mi31tvp8=
|
||||
github.com/fluxcd/helm-controller/api v0.16.0 h1:VXlt0EZVHgz2ZX1kUuKQAaQWNj1cC3PIKMRR/0aq07g=
|
||||
github.com/fluxcd/helm-controller/api v0.16.0/go.mod h1:/OeNzk18BVa7UmhGphENJdD/2GerKpMeDSxY8QYlO0o=
|
||||
github.com/fluxcd/go-git-providers v0.5.4 h1:MnByjsmXa8rMt2hTmhmtbocq7YIsTlwZKrj9lAsob4Q=
|
||||
github.com/fluxcd/go-git-providers v0.5.4/go.mod h1:4jTHTmSx3rFGnG78KUVgFYeG6vWFnKwUSr2mi31tvp8=
|
||||
github.com/fluxcd/helm-controller/api v0.17.0 h1:iWOAf5MQzWQ3QZlKQ78meFabOA61d8pkos+nDW643+s=
|
||||
github.com/fluxcd/helm-controller/api v0.17.0/go.mod h1:/OeNzk18BVa7UmhGphENJdD/2GerKpMeDSxY8QYlO0o=
|
||||
github.com/fluxcd/image-automation-controller/api v0.20.0 h1:Z+lxqif0KwccsuNOBZq5M96RXCPxtm4Xt8siC1kR6H8=
|
||||
github.com/fluxcd/image-automation-controller/api v0.20.0/go.mod h1:XhLYccGUbmJvTTpJ1jAFKZHr2e1GNXy0T85ZBO50mik=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.16.0 h1:1O1YdoK7LsJgWLyvfZTSbvQcUQCBcgJ573HA0arlQQY=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.16.0/go.mod h1:OIe3mSXc3OwQiNbiQ9vNXWYtNif31hc7WAbZWlFUUnc=
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.0 h1:Vw+2qCxeHMv0y1mfiBgVrMfcfFevBMrRfLEdfPTrb40=
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.0/go.mod h1:5MdpzJVx8+KiDIRv37zLme992BAOCgE0v1n+NOgs1lo=
|
||||
github.com/fluxcd/notification-controller/api v0.21.0 h1:D5B3TH5YtSww0SyvW1Ru5xWsh0MgHQanC/a1t3CvXq0=
|
||||
github.com/fluxcd/notification-controller/api v0.21.0/go.mod h1:gA9/j0kjh7VDuUC2Cubr9twxOdzb/0+ojcE9Lzsc9ug=
|
||||
github.com/fluxcd/kustomize-controller/api v0.21.0 h1:PizHYQuuxmO4+tnUHJ4v7cUhNEZulhmZdgnkObHjdOo=
|
||||
github.com/fluxcd/kustomize-controller/api v0.21.0/go.mod h1:5MdpzJVx8+KiDIRv37zLme992BAOCgE0v1n+NOgs1lo=
|
||||
github.com/fluxcd/notification-controller/api v0.22.0 h1:mbf9utgPbvclOhgQW85lJCzUpZ8FENkLURAwPD6leWM=
|
||||
github.com/fluxcd/notification-controller/api v0.22.0/go.mod h1:gA9/j0kjh7VDuUC2Cubr9twxOdzb/0+ojcE9Lzsc9ug=
|
||||
github.com/fluxcd/pkg/apis/acl v0.0.3 h1:Lw0ZHdpnO4G7Zy9KjrzwwBmDZQuy4qEjaU/RvA6k1lc=
|
||||
github.com/fluxcd/pkg/apis/acl v0.0.3/go.mod h1:XPts6lRJ9C9fIF9xVWofmQwftvhY25n1ps7W9xw0XLU=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.3.1 h1:wmb5D9e1+Rr3/5O3235ERuj+h2VKUArVfYYk68QKP+w=
|
||||
@@ -245,8 +247,8 @@ github.com/fluxcd/pkg/kustomize v0.0.2/go.mod h1:AFwnf3OqQmpTCuwCARTGpPRMBf0ZFJN
|
||||
github.com/fluxcd/pkg/runtime v0.12.3/go.mod h1:imJ2xYy/d4PbSinX2IefmZk+iS2c1P5fY0js8mCE4SM=
|
||||
github.com/fluxcd/pkg/runtime v0.12.4 h1:gA27RG/+adN2/7Qe03PB46Iwmye/MusPCpuS4zQ2fW0=
|
||||
github.com/fluxcd/pkg/runtime v0.12.4/go.mod h1:gspNvhAqodZgSmK1ZhMtvARBf/NGAlxmaZaIOHkJYsc=
|
||||
github.com/fluxcd/pkg/ssa v0.12.0 h1:7nF4UigU9Zk/9P/nbzUP3ah8IRC+BpB64O9iu5VnvEo=
|
||||
github.com/fluxcd/pkg/ssa v0.12.0/go.mod h1:S+qig7BTOxop0c134y8Yv8/iQST4Kt7S2xXiFkP4VMA=
|
||||
github.com/fluxcd/pkg/ssa v0.13.0 h1:LU4wf7dB9ksYdda0BEWNTBSTd68E5YwWxuPiPLAtw4Y=
|
||||
github.com/fluxcd/pkg/ssa v0.13.0/go.mod h1:XGVGjUaG152HGN6sSUj+VFK/Th5i5rj2XsXSDdlIMNU=
|
||||
github.com/fluxcd/pkg/ssh v0.3.1 h1:iQw07bkX2rScactX8WYv+uMDsufFOlg8M3fV2TNs244=
|
||||
github.com/fluxcd/pkg/ssh v0.3.1/go.mod h1:Sebfv4Um51PvomuYdMvKRncQW5dtKhZ5J5TA+wiHNSQ=
|
||||
github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk=
|
||||
@@ -254,8 +256,8 @@ github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7
|
||||
github.com/fluxcd/pkg/version v0.0.1 h1:/8asQoDXSThz3csiwi4Qo8Zb6blAxLXbtxNgeMJ9bCg=
|
||||
github.com/fluxcd/pkg/version v0.0.1/go.mod h1:WAF4FEEA9xyhngF8TDxg3UPu5fA1qhEYV8Pmi2Il01Q=
|
||||
github.com/fluxcd/source-controller/api v0.21.0/go.mod h1:Ab2qDmAUz6ZCp8UaHYLYzxyFrC1FQqEqjxiROb/Rdiw=
|
||||
github.com/fluxcd/source-controller/api v0.21.1 h1:7X39YQHmB1vmIBrHxU+YAqxwtdC9Zh+tdtMKREW3xiQ=
|
||||
github.com/fluxcd/source-controller/api v0.21.1/go.mod h1:Ab2qDmAUz6ZCp8UaHYLYzxyFrC1FQqEqjxiROb/Rdiw=
|
||||
github.com/fluxcd/source-controller/api v0.21.2 h1:J0S5NN4V8FPLrkSMXIUoUvj1X/RuTpVJSjIRF414wmc=
|
||||
github.com/fluxcd/source-controller/api v0.21.2/go.mod h1:Ab2qDmAUz6ZCp8UaHYLYzxyFrC1FQqEqjxiROb/Rdiw=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
|
||||
@@ -570,6 +572,9 @@ github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlW
|
||||
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 h1:BXxTozrOU8zgC5dkpn3J6NTRdoP+hjok/e+ACr4Hibk=
|
||||
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3/go.mod h1:x1uk6vxTiVuNt6S5R2UYgdhpj3oKojXvOXauHZ7dEnI=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
@@ -577,8 +582,9 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@@ -706,6 +712,8 @@ github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3x
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
@@ -771,6 +779,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U=
|
||||
github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8=
|
||||
github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRzJr4=
|
||||
github.com/theckman/yacspin v0.13.12/go.mod h1:Rd2+oG2LmQi5f3zC3yeZAOl245z8QOvrH4OPOJNZxLg=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
@@ -1049,6 +1059,7 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 h1:M69LAlWZCshgp0QSzyDcSsSIejIEeuaCVpmwcKwyLMk=
|
||||
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
@@ -1411,16 +1422,18 @@ sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNza
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
|
||||
sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g=
|
||||
sigs.k8s.io/kustomize/api v0.10.1 h1:KgU7hfYoscuqag84kxtzKdEC3mKMb99DPI3a0eaV1d0=
|
||||
sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8=
|
||||
sigs.k8s.io/kustomize/api v0.11.2 h1:6YvCJHFDwsLwAX7zNHBxMZi3k7dGIXI8G9l0saYQI0E=
|
||||
sigs.k8s.io/kustomize/api v0.11.2/go.mod h1:GZuhith5YcqxIDe0GnRJNx5xxPTjlwaLTt/e+ChUtJA=
|
||||
sigs.k8s.io/kustomize/cmd/config v0.9.13/go.mod h1:7547FLF8W/lTaDf0BDqFTbZxM9zqwEJqCKN9sSR0xSs=
|
||||
sigs.k8s.io/kustomize/cmd/config v0.10.2/go.mod h1:K2aW7nXJ0AaT+VA/eO0/dzFLxmpFcTzudmAgDwPY1HQ=
|
||||
sigs.k8s.io/kustomize/kustomize/v4 v4.2.0/go.mod h1:MOkR6fmhwG7hEDRXBYELTi5GSFcLwfqwzTRHW3kv5go=
|
||||
sigs.k8s.io/kustomize/kustomize/v4 v4.4.1/go.mod h1:qOKJMMz2mBP+vcS7vK+mNz4HBLjaQSWRY22EF6Tb7Io=
|
||||
sigs.k8s.io/kustomize/kyaml v0.11.0/go.mod h1:GNMwjim4Ypgp/MueD3zXHLRJEjz7RvtPae0AwlvEMFM=
|
||||
sigs.k8s.io/kustomize/kyaml v0.12.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.0 h1:9c+ETyNfSrVhxvphs+K2dzT3dh5oVPPEqPOE/cUpScY=
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.3 h1:tNNQIC+8cc+aXFTVg+RtQAOsjwUdYBZRAgYOVI3RBc4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.3/go.mod h1:/ya3Gk4diiQzlE4mBh7wykyLRFZNvqlbh+JnwQ9Vhrc=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -40,9 +41,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
controllerName = "kustomize-controller"
|
||||
controllerGroup = "kustomize.toolkit.fluxcd.io"
|
||||
mask = "**SOPS**"
|
||||
controllerName = "kustomize-controller"
|
||||
controllerGroup = "kustomize.toolkit.fluxcd.io"
|
||||
mask = "**SOPS**"
|
||||
dockercfgSecretType = "kubernetes.io/dockerconfigjson"
|
||||
typeField = "type"
|
||||
dataField = "data"
|
||||
stringDataField = "stringData"
|
||||
)
|
||||
|
||||
var defaultTimeout = 80 * time.Second
|
||||
@@ -183,7 +188,7 @@ func (b *Builder) build() (m resmap.ResMap, err error) {
|
||||
}
|
||||
|
||||
// make sure secrets are masked
|
||||
err = trimSopsData(res)
|
||||
err = maskSopsData(res)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -257,40 +262,131 @@ func (b *Builder) setOwnerLabels(res *resource.Resource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func trimSopsData(res *resource.Resource) error {
|
||||
func maskSopsData(res *resource.Resource) error {
|
||||
// sopsMess is the base64 encoded mask
|
||||
sopsMess := base64.StdEncoding.EncodeToString([]byte(mask))
|
||||
|
||||
if res.GetKind() == "Secret" {
|
||||
// get both data and stringdata maps as a secret can have both
|
||||
dataMap := res.GetDataMap()
|
||||
stringDataMap := getStringDataMap(res)
|
||||
asYaml, err := res.AsYAML()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode secret %s data: %w", res.GetName(), err)
|
||||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
|
||||
//delete any sops data as we don't want to expose it
|
||||
// delete any sops data as we don't want to expose it
|
||||
// assume that both data and stringdata are encrypted
|
||||
if bytes.Contains(asYaml, []byte("sops:")) && bytes.Contains(asYaml, []byte("mac: ENC[")) {
|
||||
// delete the sops object
|
||||
res.PipeE(yaml.FieldClearer{Name: "sops"})
|
||||
for k := range dataMap {
|
||||
dataMap[k] = sopsMess
|
||||
|
||||
secretType, err := res.GetFieldValue(typeField)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
|
||||
} else {
|
||||
for k, v := range dataMap {
|
||||
data, err := base64.StdEncoding.DecodeString(v)
|
||||
if v, ok := secretType.(string); ok && v == dockercfgSecretType {
|
||||
// if the secret is a json docker config secret, we need to mask the data with a json object
|
||||
err := maskDockerconfigjsonSopsData(dataMap)
|
||||
if err != nil {
|
||||
if _, ok := err.(base64.CorruptInputError); ok {
|
||||
return fmt.Errorf("failed to decode secret %s data: %w", res.GetName(), err)
|
||||
}
|
||||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
|
||||
if bytes.Contains(data, []byte("sops")) && bytes.Contains(data, []byte("ENC[")) {
|
||||
err = maskDockerconfigjsonSopsData(stringDataMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
|
||||
} else {
|
||||
for k := range dataMap {
|
||||
dataMap[k] = sopsMess
|
||||
}
|
||||
|
||||
for k := range stringDataMap {
|
||||
stringDataMap[k] = sopsMess
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := maskBase64EncryptedSopsData(dataMap, sopsMess)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
|
||||
err = maskSopsDataInStringDataSecret(stringDataMap, sopsMess)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// set the data and stringdata maps
|
||||
res.SetDataMap(dataMap)
|
||||
|
||||
if len(stringDataMap) > 0 {
|
||||
err = res.SetMapField(yaml.NewMapRNode(&stringDataMap), stringDataField)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mask secret %s sops data: %w", res.GetName(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getStringDataMap(rn *resource.Resource) map[string]string {
|
||||
n, err := rn.Pipe(yaml.Lookup(stringDataField))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
result := map[string]string{}
|
||||
_ = n.VisitFields(func(node *yaml.MapNode) error {
|
||||
result[yaml.GetValue(node.Key)] = yaml.GetValue(node.Value)
|
||||
return nil
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func maskDockerconfigjsonSopsData(dataMap map[string]string) error {
|
||||
sopsMess := struct {
|
||||
Mask string `json:"mask"`
|
||||
}{
|
||||
Mask: mask,
|
||||
}
|
||||
|
||||
maskJson, err := json.Marshal(sopsMess)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k := range dataMap {
|
||||
dataMap[k] = base64.StdEncoding.EncodeToString(maskJson)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func maskBase64EncryptedSopsData(dataMap map[string]string, mask string) error {
|
||||
for k, v := range dataMap {
|
||||
data, err := base64.StdEncoding.DecodeString(v)
|
||||
if err != nil {
|
||||
if _, ok := err.(base64.CorruptInputError); ok {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if bytes.Contains(data, []byte("sops")) && bytes.Contains(data, []byte("ENC[")) {
|
||||
dataMap[k] = mask
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func maskSopsDataInStringDataSecret(stringDataMap map[string]string, mask string) error {
|
||||
for k, v := range stringDataMap {
|
||||
if bytes.Contains([]byte(v), []byte("sops")) && bytes.Contains([]byte(v), []byte("ENC[")) {
|
||||
stringDataMap[k] = mask
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -97,7 +97,7 @@ type: kubernetes.io/basic-auth
|
||||
name: "secret sops secret",
|
||||
yamlStr: `apiVersion: v1
|
||||
data:
|
||||
.dockercfg: ENC[AES256_GCM,data:KHCFH3hNnc+PMfWLFEPjebf3W4z4WXbGFAANRZyZC+07z7wlrTALJM6rn8YslW4tMAWCoAYxblC5WRCszTy0h9rw0U/RGOv5H0qCgnNg/FILFUqhwo9pNfrUH+MEP4M9qxxbLKZwObpHUE7DUsKx1JYAxsI=,iv:q48lqUbUQD+0cbYcjNMZMJLRdGHi78ZmDhNAT2th9tg=,tag:QRI2SZZXQrAcdql3R5AH2g==,type:str]
|
||||
.dockerconfigjson: ENC[AES256_GCM,data:KHCFH3hNnc+PMfWLFEPjebf3W4z4WXbGFAANRZyZC+07z7wlrTALJM6rn8YslW4tMAWCoAYxblC5WRCszTy0h9rw0U/RGOv5H0qCgnNg/FILFUqhwo9pNfrUH+MEP4M9qxxbLKZwObpHUE7DUsKx1JYAxsI=,iv:q48lqUbUQD+0cbYcjNMZMJLRdGHi78ZmDhNAT2th9tg=,tag:QRI2SZZXQrAcdql3R5AH2g==,type:str]
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret
|
||||
@@ -125,7 +125,7 @@ sops:
|
||||
`,
|
||||
expected: `apiVersion: v1
|
||||
data:
|
||||
.dockercfg: KipTT1BTKio=
|
||||
.dockerconfigjson: eyJtYXNrIjoiKipTT1BTKioifQ==
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: secret
|
||||
@@ -142,7 +142,7 @@ type: kubernetes.io/dockerconfigjson
|
||||
}
|
||||
|
||||
resource := &resource.Resource{RNode: *r}
|
||||
err = trimSopsData(resource)
|
||||
err = maskSopsData(resource)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to trim sops data: %v", err)
|
||||
}
|
||||
|
||||
@@ -26,14 +26,17 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"github.com/gonvenience/bunt"
|
||||
"github.com/gonvenience/ytbx"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/homeport/dyff/pkg/dyff"
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
"github.com/theckman/yacspin"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
|
||||
@@ -52,6 +55,21 @@ func (b *Builder) Manager() (*ssa.ResourceManager, error) {
|
||||
}
|
||||
|
||||
func (b *Builder) Diff() (string, bool, error) {
|
||||
// Add a spiner
|
||||
cfg := yacspin.Config{
|
||||
Frequency: 100 * time.Millisecond,
|
||||
CharSet: yacspin.CharSets[59],
|
||||
Suffix: "Kustomization diffing...",
|
||||
SuffixAutoColon: true,
|
||||
Message: "running dry-run",
|
||||
StopCharacter: "✓",
|
||||
StopColors: []string{"fgGreen"},
|
||||
}
|
||||
spinner, err := yacspin.New(cfg)
|
||||
if err != nil {
|
||||
return "", false, fmt.Errorf("failed to create spinner: %w", err)
|
||||
}
|
||||
|
||||
output := strings.Builder{}
|
||||
createdOrDrifted := false
|
||||
res, err := b.Build()
|
||||
@@ -76,6 +94,12 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
return "", createdOrDrifted, err
|
||||
}
|
||||
|
||||
err = spinner.Start()
|
||||
if err != nil {
|
||||
return "", false, fmt.Errorf("failed to start spinner: %w", err)
|
||||
}
|
||||
|
||||
var diffErrs error
|
||||
// create an inventory of objects to be reconciled
|
||||
newInventory := newInventory()
|
||||
for _, obj := range objects {
|
||||
@@ -86,11 +110,8 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
}
|
||||
change, liveObject, mergedObject, err := resourceManager.Diff(ctx, obj, diffOptions)
|
||||
if err != nil {
|
||||
if b.kustomization.Spec.Force && ssa.IsImmutableError(err) {
|
||||
output.WriteString(writeString(fmt.Sprintf("► %s created\n", obj.GetName()), bunt.Green))
|
||||
} else {
|
||||
output.WriteString(writeString(fmt.Sprintf("✗ %v\n", err), bunt.Red))
|
||||
}
|
||||
// gather errors and continue, as we want to see all the diffs
|
||||
diffErrs = multierror.Append(diffErrs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -124,7 +145,9 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
addObjectsToInventory(newInventory, change)
|
||||
}
|
||||
|
||||
if b.kustomization.Spec.Prune {
|
||||
spinner.Message("processing inventory")
|
||||
|
||||
if b.kustomization.Spec.Prune && diffErrs == nil {
|
||||
oldStatus := b.kustomization.Status.DeepCopy()
|
||||
if oldStatus.Inventory != nil {
|
||||
diffObjects, err := diffInventory(oldStatus.Inventory, newInventory)
|
||||
@@ -137,7 +160,12 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return output.String(), createdOrDrifted, nil
|
||||
err = spinner.Stop()
|
||||
if err != nil {
|
||||
return "", createdOrDrifted, fmt.Errorf("failed to stop spinner: %w", err)
|
||||
}
|
||||
|
||||
return output.String(), createdOrDrifted, diffErrs
|
||||
}
|
||||
|
||||
func writeYamls(liveObject, mergedObject *unstructured.Unstructured) (string, string, string, error) {
|
||||
@@ -200,17 +228,31 @@ func diff(liveFile, mergedFile string, output io.Writer) error {
|
||||
}
|
||||
|
||||
func diffSopsSecret(obj, liveObject, mergedObject *unstructured.Unstructured, change *ssa.ChangeSetEntry) {
|
||||
data := obj.Object["data"]
|
||||
for _, v := range data.(map[string]interface{}) {
|
||||
// get both data and stringdata maps
|
||||
data := obj.Object[dataField]
|
||||
stringData := obj.Object[stringDataField]
|
||||
|
||||
if m, ok := data.(map[string]interface{}); ok && m != nil {
|
||||
applySopsDiff(m, liveObject, mergedObject, change)
|
||||
}
|
||||
|
||||
if m, ok := stringData.(map[string]interface{}); ok && m != nil {
|
||||
applySopsDiff(m, liveObject, mergedObject, change)
|
||||
}
|
||||
}
|
||||
|
||||
func applySopsDiff(data map[string]interface{}, liveObject, mergedObject *unstructured.Unstructured, change *ssa.ChangeSetEntry) {
|
||||
for _, v := range data {
|
||||
v, err := base64.StdEncoding.DecodeString(v.(string))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if bytes.Contains(v, []byte(mask)) {
|
||||
if liveObject != nil && mergedObject != nil {
|
||||
change.Action = string(ssa.UnchangedAction)
|
||||
dataLive := liveObject.Object["data"].(map[string]interface{})
|
||||
dataMerged := mergedObject.Object["data"].(map[string]interface{})
|
||||
dataLive := liveObject.Object[dataField].(map[string]interface{})
|
||||
dataMerged := mergedObject.Object[dataField].(map[string]interface{})
|
||||
if cmp.Diff(keys(dataLive), keys(dataMerged)) != "" {
|
||||
change.Action = string(ssa.ConfiguredAction)
|
||||
}
|
||||
|
||||
@@ -41,7 +41,10 @@ func (p *SafeRelativePath) Set(str string) error {
|
||||
return fmt.Errorf("invalid relative path '%s': %w", cleanP, err)
|
||||
}
|
||||
// NB: required, as a secure join of "./" will result in "."
|
||||
cleanP = fmt.Sprintf("./%s", strings.TrimPrefix(cleanP, "."))
|
||||
if cleanP == "." {
|
||||
cleanP = ""
|
||||
}
|
||||
cleanP = fmt.Sprintf("./%s", cleanP)
|
||||
*p = SafeRelativePath(cleanP)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -37,6 +37,13 @@ func TestRelativePath_Set(t *testing.T) {
|
||||
{"traversing absolute path", "/foo/../bar", "./bar", false},
|
||||
{"traversing overflowing absolute path", "/foo/../../../bar", "./bar", false},
|
||||
{"empty", "", "./", false},
|
||||
{"relative empty path", "./", "./", false},
|
||||
{"double relative empty path", "././", "./", false},
|
||||
{"dot path", ".foo", "./.foo", false},
|
||||
{"relative dot path", "./.foo", "./.foo", false},
|
||||
{"current directory", ".", "./", false},
|
||||
{"parent directory", "..", "./", false},
|
||||
{"parent directory more qualified", "./..", "./", false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -37,31 +38,12 @@ import (
|
||||
// Apply is the equivalent of 'kubectl apply --server-side -f'.
|
||||
// If the given manifest is a kustomization.yaml, then apply performs the equivalent of 'kubectl apply --server-side -k'.
|
||||
func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, manifestPath string) (string, error) {
|
||||
cfg, err := KubeConfig(rcg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
restMapper, err := rcg.ToRESTMapper()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
kubeClient, err := client.New(cfg, client.Options{Mapper: restMapper})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
kubePoller := polling.NewStatusPoller(kubeClient, restMapper, nil)
|
||||
|
||||
resourceManager := ssa.NewResourceManager(kubeClient, kubePoller, ssa.Owner{
|
||||
Field: "flux",
|
||||
Group: "fluxcd.io",
|
||||
})
|
||||
|
||||
objs, err := readObjects(manifestPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(objs) < 1 {
|
||||
if len(objs) == 0 {
|
||||
return "", fmt.Errorf("no Kubernetes objects found at: %s", manifestPath)
|
||||
}
|
||||
|
||||
@@ -69,11 +51,42 @@ func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, manifest
|
||||
return "", err
|
||||
}
|
||||
|
||||
changeSet, err := resourceManager.ApplyAllStaged(ctx, objs, ssa.DefaultApplyOptions())
|
||||
if err != nil {
|
||||
changeSet := ssa.NewChangeSet()
|
||||
|
||||
// contains only CRDs and Namespaces
|
||||
var stageOne []*unstructured.Unstructured
|
||||
|
||||
// contains all objects except for CRDs and Namespaces
|
||||
var stageTwo []*unstructured.Unstructured
|
||||
|
||||
for _, u := range objs {
|
||||
if ssa.IsClusterDefinition(u) {
|
||||
stageOne = append(stageOne, u)
|
||||
} else {
|
||||
stageTwo = append(stageTwo, u)
|
||||
}
|
||||
}
|
||||
|
||||
if len(stageOne) > 0 {
|
||||
cs, err := applySet(ctx, rcg, stageOne)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
changeSet.Append(cs.Entries)
|
||||
}
|
||||
|
||||
if err := waitForSet(rcg, changeSet); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(stageTwo) > 0 {
|
||||
cs, err := applySet(ctx, rcg, stageTwo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
changeSet.Append(cs.Entries)
|
||||
}
|
||||
|
||||
return changeSet.String(), nil
|
||||
}
|
||||
|
||||
@@ -98,3 +111,42 @@ func readObjects(manifestPath string) ([]*unstructured.Unstructured, error) {
|
||||
|
||||
return ssa.ReadObjects(bufio.NewReader(ms))
|
||||
}
|
||||
|
||||
func newManager(rcg genericclioptions.RESTClientGetter) (*ssa.ResourceManager, error) {
|
||||
cfg, err := KubeConfig(rcg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
restMapper, err := rcg.ToRESTMapper()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kubeClient, err := client.New(cfg, client.Options{Mapper: restMapper, Scheme: NewScheme()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kubePoller := polling.NewStatusPoller(kubeClient, restMapper, nil)
|
||||
|
||||
return ssa.NewResourceManager(kubeClient, kubePoller, ssa.Owner{
|
||||
Field: "flux",
|
||||
Group: "fluxcd.io",
|
||||
}), nil
|
||||
|
||||
}
|
||||
|
||||
func applySet(ctx context.Context, rcg genericclioptions.RESTClientGetter, objects []*unstructured.Unstructured) (*ssa.ChangeSet, error) {
|
||||
man, err := newManager(rcg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return man.ApplyAll(ctx, objects, ssa.DefaultApplyOptions())
|
||||
}
|
||||
|
||||
func waitForSet(rcg genericclioptions.RESTClientGetter, changeSet *ssa.ChangeSet) error {
|
||||
man, err := newManager(rcg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return man.WaitForSet(changeSet.ToObjMetadataSet(), ssa.WaitOptions{Interval: 2 * time.Second, Timeout: time.Minute})
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.16.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.16.0/helm-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.17.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.17.0/helm-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.20.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.20.0/kustomize-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.21.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.21.0/kustomize-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.21.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.21.0/notification-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.22.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.22.0/notification-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.21.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.21.1/source-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.21.2/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.21.2/source-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.21.1/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.20.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.16.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.21.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.21.2/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.21.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.17.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.22.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.16.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.20.0/image-automation-controller.crds.yaml
|
||||
|
||||
@@ -7,11 +7,11 @@ require (
|
||||
github.com/fluxcd/helm-controller/api v0.16.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.20.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.16.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.2
|
||||
github.com/fluxcd/notification-controller/api v0.21.0
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.2
|
||||
github.com/fluxcd/pkg/runtime v0.12.4
|
||||
github.com/fluxcd/source-controller/api v0.21.1
|
||||
github.com/fluxcd/source-controller/api v0.21.2
|
||||
github.com/hashicorp/terraform-exec v0.14.0
|
||||
github.com/libgit2/git2go/v31 v31.6.1
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
|
||||
|
||||
@@ -204,8 +204,8 @@ github.com/fluxcd/image-automation-controller/api v0.20.0 h1:Z+lxqif0KwccsuNOBZq
|
||||
github.com/fluxcd/image-automation-controller/api v0.20.0/go.mod h1:XhLYccGUbmJvTTpJ1jAFKZHr2e1GNXy0T85ZBO50mik=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.16.0 h1:1O1YdoK7LsJgWLyvfZTSbvQcUQCBcgJ573HA0arlQQY=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.16.0/go.mod h1:OIe3mSXc3OwQiNbiQ9vNXWYtNif31hc7WAbZWlFUUnc=
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.0 h1:Vw+2qCxeHMv0y1mfiBgVrMfcfFevBMrRfLEdfPTrb40=
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.0/go.mod h1:5MdpzJVx8+KiDIRv37zLme992BAOCgE0v1n+NOgs1lo=
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.2 h1:zqCvKGsNCL10WMfmjk2Sd526J6gv8ml027DwesFoZsc=
|
||||
github.com/fluxcd/kustomize-controller/api v0.20.2/go.mod h1:5MdpzJVx8+KiDIRv37zLme992BAOCgE0v1n+NOgs1lo=
|
||||
github.com/fluxcd/notification-controller/api v0.21.0 h1:D5B3TH5YtSww0SyvW1Ru5xWsh0MgHQanC/a1t3CvXq0=
|
||||
github.com/fluxcd/notification-controller/api v0.21.0/go.mod h1:gA9/j0kjh7VDuUC2Cubr9twxOdzb/0+ojcE9Lzsc9ug=
|
||||
github.com/fluxcd/pkg/apis/acl v0.0.3 h1:Lw0ZHdpnO4G7Zy9KjrzwwBmDZQuy4qEjaU/RvA6k1lc=
|
||||
@@ -218,8 +218,8 @@ github.com/fluxcd/pkg/runtime v0.12.3/go.mod h1:imJ2xYy/d4PbSinX2IefmZk+iS2c1P5f
|
||||
github.com/fluxcd/pkg/runtime v0.12.4 h1:gA27RG/+adN2/7Qe03PB46Iwmye/MusPCpuS4zQ2fW0=
|
||||
github.com/fluxcd/pkg/runtime v0.12.4/go.mod h1:gspNvhAqodZgSmK1ZhMtvARBf/NGAlxmaZaIOHkJYsc=
|
||||
github.com/fluxcd/source-controller/api v0.21.0/go.mod h1:Ab2qDmAUz6ZCp8UaHYLYzxyFrC1FQqEqjxiROb/Rdiw=
|
||||
github.com/fluxcd/source-controller/api v0.21.1 h1:7X39YQHmB1vmIBrHxU+YAqxwtdC9Zh+tdtMKREW3xiQ=
|
||||
github.com/fluxcd/source-controller/api v0.21.1/go.mod h1:Ab2qDmAUz6ZCp8UaHYLYzxyFrC1FQqEqjxiROb/Rdiw=
|
||||
github.com/fluxcd/source-controller/api v0.21.2 h1:J0S5NN4V8FPLrkSMXIUoUvj1X/RuTpVJSjIRF414wmc=
|
||||
github.com/fluxcd/source-controller/api v0.21.2/go.mod h1:Ab2qDmAUz6ZCp8UaHYLYzxyFrC1FQqEqjxiROb/Rdiw=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
|
||||
|
||||
Reference in New Issue
Block a user