Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4d7450643 | ||
|
|
0fbcfded57 | ||
|
|
fb3a434f95 | ||
|
|
4f66da84d6 | ||
|
|
b67e8aafab | ||
|
|
0b4f1d30a6 | ||
|
|
c494e6bf7e | ||
|
|
b8c57c7901 | ||
|
|
6aed4631e7 | ||
|
|
5df9118365 | ||
|
|
4a4af94d6c | ||
|
|
baa54fb84a | ||
|
|
cb6470f817 | ||
|
|
1a904e138f | ||
|
|
3b482529ff | ||
|
|
67997437db | ||
|
|
a5541eddca | ||
|
|
203157e525 | ||
|
|
655c2261ba | ||
|
|
45e446eb00 | ||
|
|
68abe37648 | ||
|
|
df6a0a3762 | ||
|
|
c35bae577f | ||
|
|
3567941eda | ||
|
|
3c95fe6380 | ||
|
|
d07f0d003c | ||
|
|
86774309db | ||
|
|
427f23e32d | ||
|
|
70cddde16c | ||
|
|
e86789b643 | ||
|
|
f52fec66bd | ||
|
|
f4926d1e45 | ||
|
|
2774c1a5cd | ||
|
|
8274bc0ea3 | ||
|
|
e9531e4d57 | ||
|
|
3a8aad7e5c | ||
|
|
ef079c5b58 | ||
|
|
50332aa2ee | ||
|
|
b47f3a57dc | ||
|
|
9a928744cc | ||
|
|
328d403507 | ||
|
|
76ffd76bd3 | ||
|
|
951589e652 | ||
|
|
7bb0704401 | ||
|
|
3aa45e72e7 | ||
|
|
67691e92e3 | ||
|
|
43388ec67b | ||
|
|
2fe3934491 | ||
|
|
f60ba95b4c | ||
|
|
4ecf541748 | ||
|
|
7994829765 | ||
|
|
ce14951436 | ||
|
|
a5ce8221a3 | ||
|
|
e6344ef18e | ||
|
|
99e60634ad | ||
|
|
6c656b7366 | ||
|
|
fc3a09b5ad | ||
|
|
b1484f2f24 | ||
|
|
7dcf884e38 | ||
|
|
b6d349da8c |
6
.github/workflows/docs.yaml
vendored
6
.github/workflows/docs.yaml
vendored
@@ -57,12 +57,12 @@ jobs:
|
||||
# image-*-controller CRDs; these use the same API group
|
||||
IMG_REFL_VER=$(controller_version image-reflector-controller)
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-reflector-controller/$IMG_REFL_VER/docs/api/image-reflector.md" > docs/components/image/reflector-api.md
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-reflector-controller/$IMG_REFL_VER/docs/spec/v1alpha1/imagerepositories.md" > docs/components/image/imagerepositories.md
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-reflector-controller/$IMG_REFL_VER/docs/spec/v1alpha1/imagepolicies.md" > docs/components/image/imagepolicies.md
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-reflector-controller/$IMG_REFL_VER/docs/spec/v1alpha2/imagerepositories.md" > docs/components/image/imagerepositories.md
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-reflector-controller/$IMG_REFL_VER/docs/spec/v1alpha2/imagepolicies.md" > docs/components/image/imagepolicies.md
|
||||
|
||||
IMG_AUTO_VER=$(controller_version image-automation-controller)
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-automation-controller/$IMG_AUTO_VER/docs/api/image-automation.md" > docs/components/image/automation-api.md
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-automation-controller/$IMG_AUTO_VER/docs/spec/v1alpha1/imageupdateautomations.md" > docs/components/image/imageupdateautomations.md
|
||||
curl -# -Lf "https://raw.githubusercontent.com/fluxcd/image-automation-controller/$IMG_AUTO_VER/docs/spec/v1alpha2/imageupdateautomations.md" > docs/components/image/imageupdateautomations.md
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
32
.github/workflows/update.yaml
vendored
32
.github/workflows/update.yaml
vendored
@@ -23,20 +23,30 @@ jobs:
|
||||
PR_BODY=""
|
||||
|
||||
bump_version() {
|
||||
local RELEASE_VERSION=$(curl -s https://api.github.com/repos/fluxcd/$1/releases | jq -r 'sort_by(.published_at) | .[-1] | .tag_name')
|
||||
local CURRENT_VERSION=$(sed -n "s/.*$1\/releases\/download\/\(.*\)\/.*/\1/p;n" manifests/bases/$1/kustomization.yaml)
|
||||
local LATEST_VERSION=$(curl -s https://api.github.com/repos/fluxcd/$1/releases | jq -r 'sort_by(.published_at) | .[-1] | .tag_name')
|
||||
local CTRL_VERSION=$(sed -n "s/.*$1\/releases\/download\/\(.*\)\/.*/\1/p;n" manifests/bases/$1/kustomization.yaml)
|
||||
local CRD_VERSION=$(sed -n "s/.*$1\/releases\/download\/\(.*\)\/.*/\1/p" manifests/crds/kustomization.yaml)
|
||||
local MOD_VERSION=$(go list -m -f '{{ .Version }}' "github.com/fluxcd/$1/api")
|
||||
|
||||
if [[ "${RELEASE_VERSION}" != "${CURRENT_VERSION}" ]]; then
|
||||
# bump kustomize
|
||||
sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${RELEASE_VERSION}\2/g" "manifests/bases/$1/kustomization.yaml"
|
||||
local changed=false
|
||||
|
||||
if [[ ! -z $(grep "github.com/fluxcd/$1/api" go.mod | awk '{print $2}') ]]; then
|
||||
# bump go mod
|
||||
go mod edit -require="github.com/fluxcd/$1/api@${RELEASE_VERSION}"
|
||||
fi
|
||||
if [[ "${CTRL_VERSION}" != "${LATEST_VERSION}" ]]; then
|
||||
sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${LATEST_VERSION}\2/g" "manifests/bases/$1/kustomization.yaml"
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# NB: special URL encoded formatting required for newlines
|
||||
PR_BODY="$PR_BODY- $1 to ${RELEASE_VERSION}%0A https://github.com/fluxcd/$1/blob/${RELEASE_VERSION}/CHANGELOG.md%0A"
|
||||
if [[ "${CRD_VERSION}" != "${LATEST_VERSION}" ]]; then
|
||||
sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${LATEST_VERSION}\2/g" "manifests/crds/kustomization.yaml"
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if [[ "${MOD_VERSION}" != "${LATEST_VERSION}" ]]; then
|
||||
go mod edit -require="github.com/fluxcd/$1/api@${LATEST_VERSION}"
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if [[ "$changed" == true ]]; then
|
||||
PR_BODY="$PR_BODY- $1 to ${LATEST_VERSION}%0A https://github.com/fluxcd/$1/blob/${LATEST_VERSION}/CHANGELOG.md%0A"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,9 @@ command will perform an upgrade if needed.`,
|
||||
|
||||
# Run bootstrap for a Git repository with a passwordless private key
|
||||
flux bootstrap git --url=ssh://git@example.com/repository.git --private-key-file=<path/to/private.key>
|
||||
|
||||
# Run bootstrap for a Git repository with a private key and password
|
||||
flux bootstrap git --url=ssh://git@example.com/repository.git --private-key-file=<path/to/private.key> --password=<password>
|
||||
`,
|
||||
RunE: bootstrapGitCmdRun,
|
||||
}
|
||||
@@ -163,6 +166,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
repositoryURL.Host = repositoryURL.Hostname()
|
||||
} else {
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
||||
secretOpts.Password = gitArgs.password
|
||||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||
secretOpts.ECDSACurve = bootstrapArgs.keyECDSACurve.Curve
|
||||
|
||||
@@ -189,7 +193,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
URL: repositoryURL.String(),
|
||||
Branch: bootstrapArgs.branch,
|
||||
Secret: bootstrapArgs.secretName,
|
||||
TargetPath: gitArgs.path.String(),
|
||||
TargetPath: gitArgs.path.ToSlash(),
|
||||
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
||||
GitImplementation: sourceGitArgs.gitImplementation.String(),
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
@@ -229,7 +233,7 @@ func transportForURL(u *url.URL) (transport.AuthMethod, error) {
|
||||
}, nil
|
||||
case "ssh":
|
||||
if bootstrapArgs.privateKeyFile != "" {
|
||||
return ssh.NewPublicKeysFromFile(u.User.Username(), bootstrapArgs.privateKeyFile, "")
|
||||
return ssh.NewPublicKeysFromFile(u.User.Username(), bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||
}
|
||||
return nil, nil
|
||||
default:
|
||||
|
||||
@@ -80,6 +80,7 @@ type githubFlags struct {
|
||||
path flags.SafeRelativePath
|
||||
teams []string
|
||||
readWriteKey bool
|
||||
reconcile bool
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -100,6 +101,7 @@ func init() {
|
||||
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.hostname, "hostname", ghDefaultDomain, "GitHub hostname")
|
||||
bootstrapGitHubCmd.Flags().Var(&githubArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path")
|
||||
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.readWriteKey, "read-write-key", false, "if true, the deploy key is configured with read/write permissions")
|
||||
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.reconcile, "reconcile", false, "if true, the configured options are also reconciled if the repository already exists")
|
||||
|
||||
bootstrapCmd.AddCommand(bootstrapGitHubCmd)
|
||||
}
|
||||
@@ -235,6 +237,9 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if !githubArgs.private {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public"))
|
||||
}
|
||||
if githubArgs.reconcile {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||
|
||||
@@ -86,6 +86,7 @@ type gitlabFlags struct {
|
||||
path flags.SafeRelativePath
|
||||
teams []string
|
||||
readWriteKey bool
|
||||
reconcile bool
|
||||
}
|
||||
|
||||
var gitlabArgs gitlabFlags
|
||||
@@ -100,6 +101,7 @@ func init() {
|
||||
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.hostname, "hostname", glDefaultDomain, "GitLab hostname")
|
||||
bootstrapGitLabCmd.Flags().Var(&gitlabArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path")
|
||||
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.readWriteKey, "read-write-key", false, "if true, the deploy key is configured with read/write permissions")
|
||||
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.reconcile, "reconcile", false, "if true, the configured options are also reconciled if the repository already exists")
|
||||
|
||||
bootstrapCmd.AddCommand(bootstrapGitLabCmd)
|
||||
}
|
||||
@@ -251,6 +253,9 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if !gitlabArgs.private {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public"))
|
||||
}
|
||||
if gitlabArgs.reconcile {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||
|
||||
@@ -74,14 +74,15 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
|
||||
|
||||
eventSources := []notificationv1.CrossNamespaceObjectReference{}
|
||||
for _, eventSource := range alertArgs.eventSources {
|
||||
kind, name := utils.ParseObjectKindName(eventSource)
|
||||
kind, name, namespace := utils.ParseObjectKindNameNamespace(eventSource)
|
||||
if kind == "" {
|
||||
return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", eventSource)
|
||||
}
|
||||
|
||||
eventSources = append(eventSources, notificationv1.CrossNamespaceObjectReference{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ type helmReleaseFlags struct {
|
||||
chart string
|
||||
chartVersion string
|
||||
targetNamespace string
|
||||
valuesFile []string
|
||||
valuesFiles []string
|
||||
valuesFrom flags.HelmReleaseValuesFrom
|
||||
saName string
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func init() {
|
||||
createHelmReleaseCmd.Flags().StringArrayVar(&helmReleaseArgs.dependsOn, "depends-on", nil, "HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'")
|
||||
createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.targetNamespace, "target-namespace", "", "namespace to install this release, defaults to the HelmRelease namespace")
|
||||
createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.saName, "service-account", "", "the name of the service account to impersonate when reconciling this HelmRelease")
|
||||
createHelmReleaseCmd.Flags().StringArrayVar(&helmReleaseArgs.valuesFile, "values", nil, "local path to values.yaml files")
|
||||
createHelmReleaseCmd.Flags().StringArrayVar(&helmReleaseArgs.valuesFiles, "values", nil, "local path to values.yaml files")
|
||||
createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.valuesFrom, "values-from", helmReleaseArgs.valuesFrom.Description())
|
||||
createCmd.AddCommand(createHelmReleaseCmd)
|
||||
}
|
||||
@@ -184,9 +184,9 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
||||
helmRelease.Spec.ServiceAccountName = helmReleaseArgs.saName
|
||||
}
|
||||
|
||||
if len(helmReleaseArgs.valuesFile) > 0 {
|
||||
var valuesMap map[string]interface{}
|
||||
for _, v := range helmReleaseArgs.valuesFile {
|
||||
if len(helmReleaseArgs.valuesFiles) > 0 {
|
||||
valuesMap := make(map[string]interface{})
|
||||
for _, v := range helmReleaseArgs.valuesFiles {
|
||||
data, err := ioutil.ReadFile(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading values from %s failed: %w", v, err)
|
||||
@@ -202,11 +202,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("unmarshaling values from %s failed: %w", v, err)
|
||||
}
|
||||
|
||||
if valuesMap == nil {
|
||||
valuesMap = jsonMap
|
||||
} else {
|
||||
valuesMap = transform.MergeMaps(valuesMap, jsonMap)
|
||||
}
|
||||
valuesMap = transform.MergeMaps(valuesMap, jsonMap)
|
||||
}
|
||||
|
||||
jsonRaw, err := json.Marshal(valuesMap)
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var createImagePolicyCmd = &cobra.Command{
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var createImageRepositoryCmd = &cobra.Command{
|
||||
|
||||
@@ -22,9 +22,8 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
var createImageUpdateCmd = &cobra.Command{
|
||||
@@ -113,25 +112,33 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: autov1.ImageUpdateAutomationSpec{
|
||||
Checkout: autov1.GitCheckoutSpec{
|
||||
GitRepositoryRef: meta.LocalObjectReference{
|
||||
Name: imageUpdateArgs.gitRepoRef,
|
||||
SourceRef: autov1.SourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: imageUpdateArgs.gitRepoRef,
|
||||
},
|
||||
|
||||
GitSpec: &autov1.GitSpec{
|
||||
Checkout: &autov1.GitCheckoutSpec{
|
||||
Reference: sourcev1.GitRepositoryRef{
|
||||
Branch: imageUpdateArgs.checkoutBranch,
|
||||
},
|
||||
},
|
||||
Commit: autov1.CommitSpec{
|
||||
Author: autov1.CommitUser{
|
||||
Name: imageUpdateArgs.authorName,
|
||||
Email: imageUpdateArgs.authorEmail,
|
||||
},
|
||||
MessageTemplate: imageUpdateArgs.commitTemplate,
|
||||
},
|
||||
Branch: imageUpdateArgs.checkoutBranch,
|
||||
},
|
||||
Interval: metav1.Duration{
|
||||
Duration: createArgs.interval,
|
||||
},
|
||||
Commit: autov1.CommitSpec{
|
||||
AuthorName: imageUpdateArgs.authorName,
|
||||
AuthorEmail: imageUpdateArgs.authorEmail,
|
||||
MessageTemplate: imageUpdateArgs.commitTemplate,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if imageUpdateArgs.pushBranch != "" {
|
||||
update.Spec.Push = &autov1.PushSpec{
|
||||
update.Spec.GitSpec.Push = &autov1.PushSpec{
|
||||
Branch: imageUpdateArgs.pushBranch,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,13 @@ For Git over HTTP/S, the provided basic authentication credentials are stored in
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--private-key-file=./private.key
|
||||
|
||||
# Create a Git SSH authentication secret with a passworded private key from file
|
||||
# The public SSH host key will still be gathered from the host
|
||||
flux create secret git podinfo-auth \
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--private-key-file=./private.key \
|
||||
--password=<password>
|
||||
|
||||
# Create a secret for a Git repository using basic authentication
|
||||
flux create secret git podinfo-auth \
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
@@ -140,6 +147,7 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
opts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(secretGitArgs.keyAlgorithm)
|
||||
opts.RSAKeyBits = int(secretGitArgs.rsaBits)
|
||||
opts.ECDSACurve = secretGitArgs.ecdsaCurve.Curve
|
||||
opts.Password = secretGitArgs.password
|
||||
case "http", "https":
|
||||
if secretGitArgs.username == "" || secretGitArgs.password == "" {
|
||||
return fmt.Errorf("for Git over HTTP/S the username and password are required")
|
||||
|
||||
@@ -101,6 +101,15 @@ For private Git repositories, the basic authentication credentials are stored in
|
||||
--branch=master \
|
||||
--private-key-file=./private.key
|
||||
|
||||
# Create a source for a Git repository using SSH authentication and a
|
||||
# private key with a password from file
|
||||
# The public SSH host key will still be gathered from the host
|
||||
flux create source git podinfo \
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--branch=master \
|
||||
--private-key-file=./private.key \
|
||||
--password=<password>
|
||||
|
||||
# Create a source for a Git repository using basic authentication
|
||||
flux create source git podinfo \
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
@@ -236,6 +245,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(sourceGitArgs.keyAlgorithm)
|
||||
secretOpts.RSAKeyBits = int(sourceGitArgs.keyRSABits)
|
||||
secretOpts.ECDSACurve = sourceGitArgs.keyECDSACurve.Curve
|
||||
secretOpts.Password = sourceGitArgs.password
|
||||
case "https":
|
||||
secretOpts.Username = sourceGitArgs.username
|
||||
secretOpts.Password = sourceGitArgs.password
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var deleteImagePolicyCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var deleteImageRepositoryCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var deleteImageUpdateCmd = &cobra.Command{
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var exportImagePolicyCmd = &cobra.Command{
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var exportImageRepositoryCmd = &cobra.Command{
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var exportImageUpdateCmd = &cobra.Command{
|
||||
|
||||
91
cmd/flux/get_all.go
Normal file
91
cmd/flux/get_all.go
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
var getAllCmd = &cobra.Command{
|
||||
Use: "all",
|
||||
Short: "Get all resources and statuses",
|
||||
Long: "The get all command print the statuses of all resources.",
|
||||
Example: ` # List all resources in a namespace
|
||||
flux get all --namespace=flux-system
|
||||
|
||||
# List all resources in all namespaces
|
||||
flux get all --all-namespaces`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := getSourceAllCmd.RunE(cmd, args)
|
||||
if err != nil {
|
||||
logError(err)
|
||||
}
|
||||
|
||||
// all get command
|
||||
var allCmd = []getCommand{
|
||||
{
|
||||
apiType: helmReleaseType,
|
||||
list: &helmReleaseListAdapter{&helmv2.HelmReleaseList{}},
|
||||
},
|
||||
{
|
||||
apiType: kustomizationType,
|
||||
list: &kustomizationListAdapter{&kustomizev1.KustomizationList{}},
|
||||
},
|
||||
{
|
||||
apiType: receiverType,
|
||||
list: receiverListAdapter{¬ificationv1.ReceiverList{}},
|
||||
},
|
||||
{
|
||||
apiType: alertProviderType,
|
||||
list: alertProviderListAdapter{¬ificationv1.ProviderList{}},
|
||||
},
|
||||
{
|
||||
apiType: alertType,
|
||||
list: &alertListAdapter{¬ificationv1.AlertList{}},
|
||||
},
|
||||
}
|
||||
|
||||
err = getImageAllCmd.RunE(cmd, args)
|
||||
if err != nil {
|
||||
logError(err)
|
||||
}
|
||||
|
||||
for _, c := range allCmd {
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
logError(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func logError(err error) {
|
||||
if !strings.Contains(err.Error(), "no matches for kind") {
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
getCmd.AddCommand(getAllCmd)
|
||||
}
|
||||
@@ -17,10 +17,12 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var getImageAllCmd = &cobra.Command{
|
||||
@@ -33,6 +35,20 @@ var getImageAllCmd = &cobra.Command{
|
||||
# List all image objects in all namespaces
|
||||
flux get images all --all-namespaces`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
var allImageCmd = []getCommand{
|
||||
{
|
||||
apiType: imageRepositoryType,
|
||||
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
|
||||
},
|
||||
{
|
||||
apiType: imagePolicyType,
|
||||
list: &imagePolicyListAdapter{&imagev1.ImagePolicyList{}},
|
||||
},
|
||||
{
|
||||
apiType: imageUpdateAutomationType,
|
||||
list: &imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},
|
||||
},
|
||||
}
|
||||
c := getCommand{
|
||||
apiType: imageRepositoryType,
|
||||
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
|
||||
@@ -41,20 +57,12 @@ var getImageAllCmd = &cobra.Command{
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
|
||||
c = getCommand{
|
||||
apiType: imagePolicyType,
|
||||
list: &imagePolicyListAdapter{&imagev1.ImagePolicyList{}},
|
||||
}
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
|
||||
c = getCommand{
|
||||
apiType: imageUpdateAutomationType,
|
||||
list: &imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},
|
||||
}
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
for _, c := range allImageCmd {
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
if !strings.Contains(err.Error(), "no matches for kind") {
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var getImagePolicyCmd = &cobra.Command{
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var getImageRepositoryCmd = &cobra.Command{
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var getImageUpdateCmd = &cobra.Command{
|
||||
|
||||
@@ -17,6 +17,8 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
@@ -32,36 +34,31 @@ var getSourceAllCmd = &cobra.Command{
|
||||
# List all sources in all namespaces
|
||||
flux get sources all --all-namespaces`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c := getCommand{
|
||||
apiType: bucketType,
|
||||
list: &bucketListAdapter{&sourcev1.BucketList{}},
|
||||
}
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
var allSourceCmd = []getCommand{
|
||||
{
|
||||
apiType: bucketType,
|
||||
list: &bucketListAdapter{&sourcev1.BucketList{}},
|
||||
},
|
||||
{
|
||||
apiType: gitRepositoryType,
|
||||
list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
|
||||
},
|
||||
{
|
||||
apiType: helmRepositoryType,
|
||||
list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
|
||||
},
|
||||
{
|
||||
apiType: helmChartType,
|
||||
list: &helmChartListAdapter{&sourcev1.HelmChartList{}},
|
||||
},
|
||||
}
|
||||
|
||||
c = getCommand{
|
||||
apiType: gitRepositoryType,
|
||||
list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
|
||||
}
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
|
||||
c = getCommand{
|
||||
apiType: helmRepositoryType,
|
||||
list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
|
||||
}
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
|
||||
c = getCommand{
|
||||
apiType: helmChartType,
|
||||
list: &helmChartListAdapter{&sourcev1.HelmChartList{}},
|
||||
}
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
for _, c := range allSourceCmd {
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
if !strings.Contains(err.Error(), "no matches for kind") {
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -19,8 +19,8 @@ package main
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
// These are general-purpose adapters for attaching methods to, for
|
||||
|
||||
@@ -18,6 +18,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
@@ -60,7 +61,7 @@ func (obj helmReleaseAdapter) reconcileSource() bool {
|
||||
return rhrArgs.syncHrWithSource
|
||||
}
|
||||
|
||||
func (obj helmReleaseAdapter) getSource() (reconcileCommand, string) {
|
||||
func (obj helmReleaseAdapter) getSource() (reconcileCommand, types.NamespacedName) {
|
||||
var cmd reconcileCommand
|
||||
switch obj.Spec.Chart.Spec.SourceRef.Kind {
|
||||
case sourcev1.HelmRepositoryKind:
|
||||
@@ -80,5 +81,8 @@ func (obj helmReleaseAdapter) getSource() (reconcileCommand, string) {
|
||||
}
|
||||
}
|
||||
|
||||
return cmd, obj.Spec.Chart.Spec.SourceRef.Name
|
||||
return cmd, types.NamespacedName{
|
||||
Name: obj.Spec.Chart.Spec.SourceRef.Name,
|
||||
Namespace: obj.Spec.Chart.Spec.SourceRef.Namespace,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var reconcileImageRepositoryCmd = &cobra.Command{
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
meta "github.com/fluxcd/pkg/apis/meta"
|
||||
)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
@@ -60,7 +61,7 @@ func (obj kustomizationAdapter) reconcileSource() bool {
|
||||
return rksArgs.syncKsWithSource
|
||||
}
|
||||
|
||||
func (obj kustomizationAdapter) getSource() (reconcileCommand, string) {
|
||||
func (obj kustomizationAdapter) getSource() (reconcileCommand, types.NamespacedName) {
|
||||
var cmd reconcileCommand
|
||||
switch obj.Spec.SourceRef.Kind {
|
||||
case sourcev1.GitRepositoryKind:
|
||||
@@ -75,5 +76,8 @@ func (obj kustomizationAdapter) getSource() (reconcileCommand, string) {
|
||||
}
|
||||
}
|
||||
|
||||
return cmd, obj.Spec.SourceRef.Name
|
||||
return cmd, types.NamespacedName{
|
||||
Name: obj.Spec.SourceRef.Name,
|
||||
Namespace: obj.Spec.SourceRef.Namespace,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ type reconcileWithSource interface {
|
||||
adapter
|
||||
reconcilable
|
||||
reconcileSource() bool
|
||||
getSource() (reconcileCommand, string)
|
||||
getSource() (reconcileCommand, types.NamespacedName)
|
||||
}
|
||||
|
||||
type reconcileWithSourceCommand struct {
|
||||
@@ -55,14 +55,13 @@ func (reconcile reconcileWithSourceCommand) run(cmd *cobra.Command, args []strin
|
||||
}
|
||||
|
||||
if reconcile.object.reconcileSource() {
|
||||
reconcileCmd, nsName := reconcile.object.getSource()
|
||||
nsCopy := rootArgs.namespace
|
||||
objectNs := reconcile.object.asClientObject().GetNamespace()
|
||||
if objectNs != "" {
|
||||
rootArgs.namespace = reconcile.object.asClientObject().GetNamespace()
|
||||
if nsName.Namespace != "" {
|
||||
rootArgs.namespace = nsName.Namespace
|
||||
}
|
||||
|
||||
reconcileCmd, sourceName := reconcile.object.getSource()
|
||||
err := reconcileCmd.run(nil, []string{sourceName})
|
||||
err := reconcileCmd.run(nil, []string{nsName.Name})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var resumeImageRepositoryCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var resumeImageUpdateCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var suspendImageRepositoryCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
)
|
||||
|
||||
var suspendImageUpdateCmd = &cobra.Command{
|
||||
|
||||
@@ -28,6 +28,9 @@ flux bootstrap git [flags]
|
||||
# Run bootstrap for a Git repository with a passwordless private key
|
||||
flux bootstrap git --url=ssh://git@example.com/repository.git --private-key-file=<path/to/private.key>
|
||||
|
||||
# Run bootstrap for a Git repository with a private key and password
|
||||
flux bootstrap git --url=ssh://git@example.com/repository.git --private-key-file=<path/to/private.key> --password=<password>
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
@@ -56,6 +56,7 @@ flux bootstrap github [flags]
|
||||
--personal if true, the owner is assumed to be a GitHub user; otherwise an org
|
||||
--private if true, the repository is setup or configured as private (default true)
|
||||
--read-write-key if true, the deploy key is configured with read/write permissions
|
||||
--reconcile if true, the configured options are also reconciled if the repository already exists
|
||||
--repository string GitHub repository name
|
||||
--team stringArray GitHub team to be given maintainer access
|
||||
```
|
||||
|
||||
@@ -53,6 +53,7 @@ flux bootstrap gitlab [flags]
|
||||
--personal if true, the owner is assumed to be a GitLab user; otherwise a group
|
||||
--private if true, the repository is setup or configured as private (default true)
|
||||
--read-write-key if true, the deploy key is configured with read/write permissions
|
||||
--reconcile if true, the configured options are also reconciled if the repository already exists
|
||||
--repository string GitLab repository name
|
||||
--team stringArray GitLab teams to be given maintainer access
|
||||
```
|
||||
|
||||
@@ -31,6 +31,13 @@ flux create secret git [name] [flags]
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--private-key-file=./private.key
|
||||
|
||||
# Create a Git SSH authentication secret with a passworded private key from file
|
||||
# The public SSH host key will still be gathered from the host
|
||||
flux create secret git podinfo-auth \
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--private-key-file=./private.key \
|
||||
--password=<password>
|
||||
|
||||
# Create a secret for a Git repository using basic authentication
|
||||
flux create secret git podinfo-auth \
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
|
||||
@@ -54,6 +54,15 @@ flux create source git [name] [flags]
|
||||
--branch=master \
|
||||
--private-key-file=./private.key
|
||||
|
||||
# Create a source for a Git repository using SSH authentication and a
|
||||
# private key with a password from file
|
||||
# The public SSH host key will still be gathered from the host
|
||||
flux create source git podinfo \
|
||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||
--branch=master \
|
||||
--private-key-file=./private.key \
|
||||
--password=<password>
|
||||
|
||||
# Create a source for a Git repository using basic authentication
|
||||
flux create source git podinfo \
|
||||
--url=https://github.com/stefanprodan/podinfo \
|
||||
|
||||
@@ -31,6 +31,7 @@ The get sub-commands print the statuses of Flux resources.
|
||||
* [flux](../flux/) - Command line utility for assembling Kubernetes CD pipelines
|
||||
* [flux get alert-providers](../flux_get_alert-providers/) - Get Provider statuses
|
||||
* [flux get alerts](../flux_get_alerts/) - Get Alert statuses
|
||||
* [flux get all](../flux_get_all/) - Get all resources and statuses
|
||||
* [flux get helmreleases](../flux_get_helmreleases/) - Get HelmRelease statuses
|
||||
* [flux get images](../flux_get_images/) - Get image automation object status
|
||||
* [flux get kustomizations](../flux_get_kustomizations/) - Get Kustomization statuses
|
||||
|
||||
46
docs/cmd/flux_get_all.md
Normal file
46
docs/cmd/flux_get_all.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "flux get all command"
|
||||
---
|
||||
## flux get all
|
||||
|
||||
Get all resources and statuses
|
||||
|
||||
### Synopsis
|
||||
|
||||
The get all command print the statuses of all resources.
|
||||
|
||||
```
|
||||
flux get all [flags]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# List all resources in a namespace
|
||||
flux get all --namespace=flux-system
|
||||
|
||||
# List all resources in all namespaces
|
||||
flux get all --all-namespaces
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for all
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
-A, --all-namespaces list the requested object(s) across all namespaces
|
||||
--context string kubernetes context to use
|
||||
--kubeconfig string absolute path to the kubeconfig file
|
||||
-n, --namespace string the namespace scope for this operation (default "flux-system")
|
||||
--timeout duration timeout for this operation (default 5m0s)
|
||||
--verbose print generated objects
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [flux get](../flux_get/) - Get the resources and their status
|
||||
|
||||
@@ -287,20 +287,24 @@ $ flux create image update my-app-auto \
|
||||
--export > ./$AUTO_PATH/my-app-auto.yaml
|
||||
$ cat my-app-auto.yaml
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: my-app-auto
|
||||
namespace: flux-system
|
||||
spec:
|
||||
checkout:
|
||||
branch: main
|
||||
gitRepositoryRef:
|
||||
name: flux-system
|
||||
commit:
|
||||
authorEmail: fluxbot@example.com
|
||||
authorName: FluxBot
|
||||
interval: 5m0s
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
git:
|
||||
checkout:
|
||||
ref:
|
||||
branch: main
|
||||
commit:
|
||||
author:
|
||||
email: fluxbot@example.com
|
||||
name: FluxBot
|
||||
```
|
||||
|
||||
#### Commit and check that the automation object works
|
||||
@@ -357,14 +361,8 @@ metadata:
|
||||
annotations:
|
||||
fluxcd.io/automated: "true"
|
||||
fluxcd.io/tag.app: semver:^5.0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
@@ -395,14 +393,8 @@ metadata:
|
||||
annotations:
|
||||
fluxcd.io/automated: "true"
|
||||
fluxcd.io/tag.app: semver:^5.0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
@@ -420,7 +412,7 @@ $ flux create image repository podinfo-image \
|
||||
--export > ./$AUTO_PATH/podinfo-image.yaml
|
||||
$ cat ./$AUTO_PATH/podinfo-image.yaml
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImageRepository
|
||||
metadata:
|
||||
name: podinfo-image
|
||||
@@ -525,7 +517,7 @@ Say you want to filter for only images that are from `main` branch, and pick the
|
||||
`ImagePolicy` would look like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImagePolicy
|
||||
metadata:
|
||||
name: my-app-policy
|
||||
@@ -569,7 +561,7 @@ example, you might put a target environment as well as the version in your image
|
||||
Then you would use an `ImagePolicy` similar to this one:
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImagePolicy
|
||||
metadata:
|
||||
name: my-app-policy
|
||||
@@ -600,7 +592,7 @@ $ flux create image policy my-app-policy \
|
||||
--export > ./$AUTO_PATH/my-app-policy.yaml
|
||||
$ cat ./$AUTO_PATH/my-app-policy.yaml
|
||||
---
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImagePolicy
|
||||
metadata:
|
||||
name: my-app-policy
|
||||
@@ -659,14 +651,8 @@ metadata:
|
||||
annotations:
|
||||
fluxcd.io/automated: "true"
|
||||
fluxcd.io/tag.app: semver:^5.0 # <-- `.app` here
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- name: app # <-- targets `app` here
|
||||
@@ -685,14 +671,8 @@ kind: Deployment
|
||||
metadata:
|
||||
namespace: default
|
||||
name: my-app
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
|
||||
@@ -5,11 +5,11 @@ This guide will learn you everything you need to know to be able to migrate from
|
||||
## Overview of changes
|
||||
|
||||
### Support for Helm v2 dropped
|
||||
|
||||
|
||||
The Helm Operator offered support for both Helm v2 and v3, due to Kubernetes client incompatibility issues between the versions. This has blocked the Helm Operator from being able to upgrade to a newer v3 version since the release of `3.2.0`.
|
||||
|
||||
In combination with the fact that [Helm v2 reaches end of life after November 13, 2020](https://helm.sh/blog/helm-v2-deprecation-timeline/), support for Helm v2 has been dropped.
|
||||
|
||||
|
||||
### Helm and Git repositories, and even Helm charts are now Custom Resources
|
||||
|
||||
When working with the Helm Operator, you had to mount various files to either make it recognize new (private) Helm repositories or make it gain access to Helm and/or Git repositories. While this approach was declarative, it did not provide a great user experience and was at times hard to set up.
|
||||
@@ -41,7 +41,7 @@ For a comprehensive overview, see the [API spec changes](#api-spec-changes).
|
||||
### Helm storage drift detection no longer relies on dry-runs
|
||||
|
||||
The Helm Controller no longer uses dry-runs as a way to detect mutations to the Helm storage. Instead, it uses a simpler model of bookkeeping based on the observed state and revisions. This has resulted in much better performance, a lower memory and CPU footprint, and more reliable drift detection.
|
||||
|
||||
|
||||
### No longer supports [Helm downloader plugins](https://helm.sh/docs/topics/plugins/#downloader-plugins)
|
||||
|
||||
We have reduced our usage of Helm packages to a bare minimum (that being: as much as we need to be able to work with chart repositories and charts), and are avoiding shell outs as much as we can.
|
||||
@@ -55,10 +55,10 @@ We are aware some of our users are using this functionality to be able to retrie
|
||||
Support for values references to `ConfigMap` and `Secret` resources in other namespaces than the namespace of the `HelmRelease` has been dropped, as this allowed information from other namespaces to leak into the composed values for the Helm release.
|
||||
|
||||
### Values from external source references (URLs) are no longer supported
|
||||
|
||||
|
||||
We initially introduced this feature to support alternative (production focused) `values.yaml` files that sometimes come with charts. It was also used by users to use generic and/or dynamic `values.yaml` files in their `HelmRelease` resources.
|
||||
|
||||
The former can now be achieved by defining a [`ValuesFile` overwrite in the `HelmChartTemplateSpec`](#chart-file-references), which will make the Source Controller look for the referenced file in the chart, and overwrite the default values with the contents from that file.
|
||||
The former can now be achieved by defining a [`ValuesFiles` overwrite in the `HelmChartTemplateSpec`](#chart-file-references), which will make the Source Controller look for the referenced file in the chart, and overwrite the default values with the contents from that file.
|
||||
|
||||
Support for the latter use has been dropped, as it goes against the principles of GitOps and declarative configuration. You can not reliably restore the cluster state from a Git repository if the configuration of a service relies on some URL being available.
|
||||
|
||||
@@ -76,7 +76,7 @@ We have added support for depends-on relationships to install `HelmRelease` reso
|
||||
|
||||
Entries defined in the `spec.dependsOn` list of the `HelmRelease` must be in a `Ready` state before the Helm Controller proceeds with installation and/or upgrade actions.
|
||||
|
||||
Note that this does not account for upgrade ordering. Kubernetes only allows applying one resource (`HelmRelease` in this case) at a time, so there is no way for the controller to know when a dependency `HelmRelease` may be updated.
|
||||
Note that this does not account for upgrade ordering. Kubernetes only allows applying one resource (`HelmRelease` in this case) at a time, so there is no way for the controller to know when a dependency `HelmRelease` may be updated.
|
||||
|
||||
Also, circular dependencies between `HelmRelease` resources must be avoided, otherwise the interdependent `HelmRelease` resources will never be reconciled.
|
||||
|
||||
@@ -457,13 +457,15 @@ spec:
|
||||
version: 1.2.3
|
||||
# Alternative values file to use as the default values,
|
||||
# expected to be a relative path in the sourceRef
|
||||
valuesFile: values-prod.yaml
|
||||
valuesFiles:
|
||||
- values.yaml
|
||||
- values-prod.yaml
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: my-repository
|
||||
```
|
||||
|
||||
When the `valuesFile` is defined, the chart will be (re)packaged with the values from the referenced file as the default values. Note that this behavior is different from the Helm Operator and requires a full set of alternative values, as the referenced values are no longer merged with the default values.
|
||||
When `valuesFiles` is defined, the chart will be (re)packaged with the values from the referenced files as the default values, merged in the order they appear. Note that this behavior is different from the Helm Operator as the default values (values.yaml) are not merged by default and must be explicitly added to the list.
|
||||
|
||||
##### External source references
|
||||
|
||||
@@ -662,7 +664,7 @@ spec:
|
||||
|
||||
## Migration strategy
|
||||
|
||||
Due to the high number of changes to the API spec, there are no detailed instructions available to provide a simple migration path. But there is a [simple procedure to follow](#steps), which combined with the detailed list of [API spec changes](#api-spec-changes) should make the migration path relatively easy.
|
||||
Due to the high number of changes to the API spec, there are no detailed instructions available to provide a simple migration path. But there is a [simple procedure to follow](#steps), which combined with the detailed list of [API spec changes](#api-spec-changes) should make the migration path relatively easy.
|
||||
|
||||
Here are some things to know:
|
||||
|
||||
@@ -742,6 +744,81 @@ Gradually migrating to the Helm Controller is possible by scaling down the Helm
|
||||
|
||||
While doing this, make sure that once you scale up the Helm Operator again, there are no old and new `HelmRelease` resources pointing towards the same release, as they will fight over the release.
|
||||
|
||||
Alternatively, you can gradually migrate per namespace without ever needing to shut the Helm Operator down, enabling no continuous delivery interruption on most namespaces. To do so, you can customize the Helm Operator roles associated to its `ServiceAccount` to prevent it from interfering with the Helm Controller in namespaces you are migrating. First, create a new `ClusterRole` for the Helm Operator to operate in "read-only" mode cluster-wide:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: helm-operator-ro
|
||||
rules:
|
||||
- apiGroups: ['*']
|
||||
resources: ['*']
|
||||
verbs:
|
||||
- get
|
||||
- watch
|
||||
- list
|
||||
- nonResourceURLs: ['*']
|
||||
verbs: ['*']
|
||||
```
|
||||
|
||||
By default, [the `helm-operator` `ServiceAccount` is bound to a `ClusterRole` that allows it to create, patch and delete resources in all namespaces](https://github.com/fluxcd/helm-operator/blob/1baacd6dee865b57da80e0e767286ed68d578246/deploy/rbac.yaml#L9-L36). Bind the `ServiceAccount` to the new `helm-operator-ro` `ClusterRole`:
|
||||
|
||||
```diff
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: helm-operator
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
- name: helm-operator
|
||||
+ name: helm-operator-ro
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: helm-operator
|
||||
namespace: flux
|
||||
```
|
||||
|
||||
Finally, create `RoleBindings` for each namespace, but the one you are currently migrating:
|
||||
|
||||
```yaml
|
||||
# Create a `RoleBinding` for each namespace the Helm Operator is allowed to process `HelmReleases` in
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: helm-operator
|
||||
namespace: helm-operator-watched-namespace
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: helm-operator
|
||||
subjects:
|
||||
- name: helm-operator
|
||||
namespace: flux
|
||||
kind: ServiceAccount
|
||||
# Do not create the following to prevent the Helm Operator from watching `HelmReleases` in `helm-controller-watched-namespace`
|
||||
# ---
|
||||
# apiVersion: rbac.authorization.k8s.io/v1
|
||||
# kind: RoleBinding
|
||||
# metadata:
|
||||
# name: helm-operator
|
||||
# namespace: helm-controller-watched-namespace
|
||||
# roleRef:
|
||||
# apiGroup: rbac.authorization.k8s.io
|
||||
# kind: ClusterRole
|
||||
# name: helm-operator
|
||||
# subjects:
|
||||
# - name: helm-operator
|
||||
# namespace: flux
|
||||
# kind: ServiceAccount
|
||||
```
|
||||
|
||||
If you are using [the Helm Operator chart](https://github.com/fluxcd/helm-operator/tree/master/chart/helm-operator), make sure to set `rbac.create` to `false` in order to take over `ClusterRoleBindings` and `RoleBindings` as you wish.
|
||||
|
||||
### Deleting old resources
|
||||
|
||||
Once you have migrated all your `HelmRelease` resources to the Helm Controller. You can remove all of the old resources by removing the old Custom Resource Definition.
|
||||
@@ -781,4 +858,4 @@ For more details please see this [answer](../faq/index.md#can-i-use-flux-helmrel
|
||||
|
||||
### I have another question
|
||||
|
||||
Given the amount of changes, it is quite possible that this document did not provide you with a clear answer for you specific setup. If this applies to you, do not hestitate to ask for help in the [GitHub Discussions](https://github.com/fluxcd/flux2/discussions/new?category_id=31999889) or on the [`#flux` CNCF Slack channel](https://slack.cncf.io)!
|
||||
Given the amount of changes, it is quite possible that this document did not provide you with a clear answer for you specific setup. If this applies to you, do not hesitate to ask for help in the [GitHub Discussions](https://github.com/fluxcd/flux2/discussions/new?category_id=31999889) or on the [`#flux` CNCF Slack channel](https://slack.cncf.io)!
|
||||
|
||||
@@ -9,7 +9,7 @@ The helm-controller is part of the default toolkit installation.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To follow this guide you'll need a Kubernetes cluster with the GitOps
|
||||
To follow this guide you'll need a Kubernetes cluster with the GitOps
|
||||
toolkit controllers installed on it.
|
||||
Please see the [get started guide](../get-started/index.md)
|
||||
or the [installation guide](installation.md).
|
||||
@@ -54,7 +54,7 @@ The `url` can be any HTTP/S Helm repository URL.
|
||||
HTTP/S basic and TLS authentication can be configured for private
|
||||
Helm repositories. See the [`HelmRepository` CRD docs](../components/source/helmrepositories.md)
|
||||
for more details.
|
||||
|
||||
|
||||
### Git repository
|
||||
|
||||
Charts from Git repositories can be released by declaring a
|
||||
@@ -68,7 +68,7 @@ later on in the guide).
|
||||
**There is one caveat you should be aware of:** to make the
|
||||
source-controller produce a new chart artifact, the `version` in the
|
||||
`Chart.yaml` of the chart must be bumped.
|
||||
|
||||
|
||||
An example `GitRepository`:
|
||||
|
||||
```yaml
|
||||
@@ -378,12 +378,14 @@ spec:
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: bitnami
|
||||
valuesFile: values-production.yaml
|
||||
valuesFiles:
|
||||
- values.yaml
|
||||
- values-production.yaml
|
||||
values:
|
||||
replicaCount: 5
|
||||
```
|
||||
|
||||
If the `spec.chart.spec.valuesFile` doesn't exists inside the chart, helm-controller will not be able to
|
||||
If the `spec.chart.spec.valuesFiles` doesn't exists inside the chart, helm-controller will not be able to
|
||||
fetch the chart. To determine why the `HelmChart` fails to produce an artifact, you can inspect the status with:
|
||||
|
||||
```console
|
||||
@@ -439,7 +441,7 @@ First generate a random string and create a secret with a `token` field:
|
||||
TOKEN=$(head -c 12 /dev/urandom | shasum | cut -d ' ' -f1)
|
||||
echo $TOKEN
|
||||
|
||||
kubectl -n flux-system create secret generic webhook-token \
|
||||
kubectl -n flux-system create secret generic webhook-token \
|
||||
--from-literal=token=$TOKEN
|
||||
```
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ flux create image repository podinfo \
|
||||
The above command generates the following manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImageRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
@@ -177,7 +177,7 @@ flux create image policy podinfo \
|
||||
The above command generates the following manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImagePolicy
|
||||
metadata:
|
||||
name: podinfo
|
||||
@@ -258,23 +258,27 @@ flux create image update flux-system \
|
||||
The above command generates the following manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
spec:
|
||||
checkout:
|
||||
branch: main
|
||||
gitRepositoryRef:
|
||||
name: flux-system
|
||||
commit:
|
||||
authorEmail: fluxcdbot@users.noreply.github.com
|
||||
authorName: fluxcdbot
|
||||
messageTemplate: '{{range .Updated.Images}}{{println .}}{{end}}'
|
||||
interval: 1m0s
|
||||
push:
|
||||
branch: main
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
git:
|
||||
checkout:
|
||||
ref:
|
||||
branch: main
|
||||
commit:
|
||||
author:
|
||||
email: fluxcdbot@users.noreply.github.com
|
||||
name: fluxcdbot
|
||||
messageTemplate: '{{range .Updated.Images}}{{println .}}{{end}}'
|
||||
push:
|
||||
branch: main
|
||||
update:
|
||||
path: ./clusters/my-cluster
|
||||
strategy: Setters
|
||||
@@ -387,21 +391,20 @@ images:
|
||||
|
||||
## Push updates to a different branch
|
||||
|
||||
With `.spec.push.branch` you can configure Flux to push the image updates to different branch
|
||||
With `.spec.git.push.branch` you can configure Flux to push the image updates to different branch
|
||||
than the one used for checkout. If the specified branch doesn't exist, Flux will create it for you.
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: flux-system
|
||||
spec:
|
||||
checkout:
|
||||
branch: main
|
||||
gitRepositoryRef:
|
||||
name: flux-system
|
||||
push:
|
||||
branch: image-updates
|
||||
spec:
|
||||
git:
|
||||
checkout:
|
||||
ref:
|
||||
branch: main
|
||||
push:
|
||||
branch: flux-image-updates
|
||||
```
|
||||
|
||||
You can use CI automation e.g. GitHub Actions such as
|
||||
@@ -412,39 +415,40 @@ This way you can manually approve the image updates before they are applied on y
|
||||
|
||||
## Configure the commit message
|
||||
|
||||
The `.spec.commit.messageTemplate` field is a string which is used as a template for the commit message.
|
||||
The `.spec.git.commit.messageTemplate` field is a string which is used as a template for the commit message.
|
||||
|
||||
The message template is a [Go text template](https://golang.org/pkg/text/template/) that
|
||||
lets you range over the objects and images e.g.:
|
||||
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
kind: ImageUpdateAutomation
|
||||
metadata:
|
||||
name: flux-system
|
||||
spec:
|
||||
commit:
|
||||
messageTemplate: |
|
||||
Automated image update
|
||||
git:
|
||||
commit:
|
||||
messageTemplate: |
|
||||
Automated image update
|
||||
|
||||
Automation name: {{ .AutomationObject }}
|
||||
Automation name: {{ .AutomationObject }}
|
||||
|
||||
Files:
|
||||
{{ range $filename, $_ := .Updated.Files -}}
|
||||
- {{ $filename }}
|
||||
{{ end -}}
|
||||
Files:
|
||||
{{ range $filename, $_ := .Updated.Files -}}
|
||||
- {{ $filename }}
|
||||
{{ end -}}
|
||||
|
||||
Objects:
|
||||
{{ range $resource, $_ := .Updated.Objects -}}
|
||||
- {{ $resource.Kind }} {{ $resource.Name }}
|
||||
{{ end -}}
|
||||
Objects:
|
||||
{{ range $resource, $_ := .Updated.Objects -}}
|
||||
- {{ $resource.Kind }} {{ $resource.Name }}
|
||||
{{ end -}}
|
||||
|
||||
Images:
|
||||
{{ range .Updated.Images -}}
|
||||
- {{.}}
|
||||
{{ end -}}
|
||||
authorEmail: flux@example.com
|
||||
authorName: flux
|
||||
Images:
|
||||
{{ range .Updated.Images -}}
|
||||
- {{.}}
|
||||
{{ end -}}
|
||||
author:
|
||||
email: fluxcdbot@users.noreply.github.com
|
||||
name: fluxcdbot
|
||||
```
|
||||
|
||||
## Trigger image updates with webhooks
|
||||
@@ -884,7 +888,7 @@ Create a directory in your control repository and save this `kustomization.yaml`
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- git@github.com/fluxcd/flux2//manifests/integrations/registry-credentials-sync/azure
|
||||
- https://github.com/fluxcd/flux2/manifests/integrations/registry-credentials-sync/azure?ref=main
|
||||
patchesStrategicMerge:
|
||||
- config-patches.yaml
|
||||
```
|
||||
|
||||
@@ -337,16 +337,23 @@ please see [fluxcd/terraform-provider-flux](https://github.com/fluxcd/terraform-
|
||||
|
||||
## Customize Flux manifests
|
||||
|
||||
You can customize the Flux components in the Git repository where you've run bootstrap with Kustomize patches.
|
||||
You can customize the Flux components before or after running bootstrap.
|
||||
|
||||
First clone the repository locally and generate a `kustomization.yaml` file with:
|
||||
Assuming you want to customise the Flux controllers before they get deployed on the cluster,
|
||||
first you'll need to create a Git repository and clone it locally.
|
||||
|
||||
Create the file structure required by bootstrap with:
|
||||
|
||||
```sh
|
||||
cd ./clusters/production && kustomize create --autodetect
|
||||
mkdir -p clusters/my-cluster/flux-system
|
||||
touch clusters/my-cluster/flux-system/gotk-components.yaml \
|
||||
clusters/my-cluster/flux-system/gotk-patches.yaml \
|
||||
clusters/my-cluster/flux-system/gotk-sync.yaml \
|
||||
clusters/my-cluster/flux-system/kustomization.yaml
|
||||
```
|
||||
|
||||
Assuming you want to add custom annotations and labels to the Flux controllers in `clusters/production`.
|
||||
Create a Kustomize patch and set the metadata for source-controller and kustomize-controller pods:
|
||||
Assuming you want to add custom annotations and labels to the Flux controllers,
|
||||
edit `clusters/my-cluster/gotk-patches.yaml` and set the metadata for source-controller and kustomize-controller pods:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
@@ -376,26 +383,37 @@ spec:
|
||||
custom: label
|
||||
```
|
||||
|
||||
Save the above file as `flux-system-patch.yaml` inside the `clusters/production` dir.
|
||||
|
||||
Edit `clusters/production/kustomization.yaml` and add the patch:
|
||||
Edit `clusters/my-cluster/kustomization.yaml` and set the resources and patches:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- flux-system
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patchesStrategicMerge:
|
||||
- flux-system-patch.yaml
|
||||
- gotk-patches.yaml
|
||||
```
|
||||
|
||||
Push the changes to main branch:
|
||||
|
||||
```sh
|
||||
git add -A && git commit -m "add production metadata" && git push
|
||||
git add -A && git commit -m "add flux customisations" && git push
|
||||
```
|
||||
|
||||
Flux will detect the change and will update itself on the production cluster.
|
||||
Now run the bootstrap for `clusters/my-cluster`:
|
||||
|
||||
```sh
|
||||
flux bootstrap git \
|
||||
--url=ssh://git@<host>/<org>/<repository> \
|
||||
--branch=main \
|
||||
--path=clusters/my-cluster
|
||||
```
|
||||
|
||||
When the controllers are deployed for the first time on your cluster, they will contain all
|
||||
the customisations from `gotk-patches.yaml`.
|
||||
|
||||
You can make changes to the patches after bootstrap and Flux will apply them in-cluster on its own.
|
||||
|
||||
## Dev install
|
||||
|
||||
|
||||
@@ -114,8 +114,8 @@ built from that branch.
|
||||
Here is an example that filters for only images built from `main` branch, and selects the most
|
||||
recent according the timestamp (created with `date +%s`):
|
||||
|
||||
```
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImagePolicy
|
||||
metadata:
|
||||
name: image-repo-policy
|
||||
@@ -133,8 +133,8 @@ spec:
|
||||
|
||||
If you don't care about the branch, that part can be a wildcard in the pattern:
|
||||
|
||||
```
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||
kind: ImagePolicy
|
||||
metadata:
|
||||
name: image-repo-policy
|
||||
|
||||
@@ -211,7 +211,7 @@ If you want to use Managed Identities, install or enable [AAD Pod Identity](#aad
|
||||
Patch kustomize-controller with the proper Azure credentials, so that it may access your Azure Key Vault, and then begin
|
||||
committing SOPS encrypted files to the Git repository with the proper Azure Key Vault configuration.
|
||||
|
||||
See the [Mozilla SOPS Azure Guide](../../guides/mozilla-sops/#azure) for further detail.
|
||||
See the [Mozilla SOPS Azure Guide](../guides/mozilla-sops.md#azure) for further detail.
|
||||
|
||||
## Image Updates with Azure Container Registry
|
||||
|
||||
|
||||
1279
docs/use-cases/gh-actions-manifest-generation.md
Normal file
1279
docs/use-cases/gh-actions-manifest-generation.md
Normal file
File diff suppressed because it is too large
Load Diff
208
docs/use-cases/helm.md
Normal file
208
docs/use-cases/helm.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# Flux for Helm Users
|
||||
|
||||
Welcome Helm users!
|
||||
We think Flux's Helm Controller is the best way to do Helm according to GitOps principles, and we're dedicated to doing what we can to help you feel the same way.
|
||||
|
||||
## What Does Flux add to Helm?
|
||||
|
||||
Helm 3 was designed with both a client and an SDK, but no running software agents.
|
||||
This architecture intended anything outside of the client scope to be addressed by other tools in the ecosystem, which could then make use of Helm's SDK.
|
||||
|
||||
Built on Kubernetes controller-runtime, Flux's Helm Controller is an example of a mature software agent that uses Helm's SDK to full effect.
|
||||
<!-- Flux is the only CD project that uses Helm as a library – not shelling out to the client – and does not fork the SDK to diverge from how Helm does things. -->
|
||||
|
||||
Flux's biggest addition to Helm is a structured declaration layer for your releases that automatically gets reconciled to your cluster based on your configured rules:
|
||||
|
||||
- While the Helm client commands let you imperatively do things
|
||||
- Flux Helm Custom Resources let you declare what you want the Helm SDK to do automatically
|
||||
|
||||
Additional benefits Flux adds to Helm include:
|
||||
|
||||
- Managing / structuring multiple environments
|
||||
- A control loop, with configurable retry logic
|
||||
- Automated drift detection between the desired and actual state of your operations
|
||||
- Automated responses to that drift, including reconciliation, notifications, and unified logging
|
||||
|
||||
## Getting Started
|
||||
|
||||
The simplest way to explain is by example.
|
||||
Lets translate imperative Helm commands to Flux Helm Controller Custom Resources:
|
||||
|
||||
Helm client:
|
||||
|
||||
```console
|
||||
helm repo add traefik https://helm.traefik.io/traefik
|
||||
helm install my-traefik traefik/traefik \
|
||||
--version 9.18.2 \
|
||||
--namespace traefik
|
||||
```
|
||||
|
||||
Flux client:
|
||||
|
||||
```console
|
||||
flux create source helm traefik --url https://helm.traefik.io/traefik
|
||||
flux create helmrelease --chart my-traefik \
|
||||
--source HelmRepository/traefik \
|
||||
--chart-version 9.18.2 \
|
||||
--namespace traefik
|
||||
```
|
||||
|
||||
The main difference is Flux client will not imperatively create resources in the cluster.
|
||||
Instead these commands create Custom Resource *files*, which are committed to version control as instructions only (note: you may use the `--export` flag to manage any file edits with finer grained control before pushing to version control).
|
||||
Separately, the Flux Helm Controller software agent automatically reconciles these instructions with the running state of your cluster based on your configured rules.
|
||||
|
||||
Lets check out what the Custom Resoruce instruction files look like:
|
||||
|
||||
```yaml
|
||||
# /flux/boot/traefik/helmrepo.yaml
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: traefik
|
||||
spec:
|
||||
interval: 1m0s
|
||||
url: https://helm.traefik.io/traefik
|
||||
```
|
||||
|
||||
```yaml
|
||||
# /flux/boot/traefik/helmrelease.yaml
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: traefik
|
||||
namespace: traefik
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
chart: traefik
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: traefik
|
||||
version: 9.18.2
|
||||
interval: 1m0s
|
||||
```
|
||||
|
||||
<!-- Using the Flux Kustomize Controller, these are automatically applied to your cluster, just as any other Kubernetes resources are. Note that while you may find value in combining Kustomize overlays with your Helm Controller manifests to further reduce file duplication, that is entirely optional and unrelated to the Helm Controller. -->
|
||||
|
||||
Once these are applied to your cluster, the Flux Helm Controller automatically uses the Helm SDK to do your bidding according to the rules you've set.
|
||||
|
||||
Why is this important?
|
||||
If you or your team has ever collaborated with multiple engineers on one or more apps, and/or in more than one namespace or cluster, you probably have a good idea of how declarative, automatic reconciliation can help solve common problems.
|
||||
If not, or either way, you may want to check out this [short introduction to GitOps](https://youtu.be/r-upyR-cfDY).
|
||||
|
||||
## Customizing Your Release
|
||||
|
||||
While Helm charts are usually installable using default configurations, users will often customize charts with their preferred configuration by [overriding the default values](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing).
|
||||
The Helm client allows this by imperatively specifying override values with `--set` on the command line, and in additional `--values` files. For example:
|
||||
|
||||
```console
|
||||
helm install my-traefik traefik/traefik --set service.type=ClusterIP
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```console
|
||||
helm install my-traefik traefik/traefik --values ci/kind-values.yaml
|
||||
```
|
||||
|
||||
where `ci/kind-values.yaml` contains:
|
||||
|
||||
```yaml
|
||||
service:
|
||||
type: ClusterIP
|
||||
```
|
||||
|
||||
Flux Helm Controller allows these same YAML values overrides on the `HelmRelease` CRD.
|
||||
These can be declared directly in `spec.values`:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
values:
|
||||
service:
|
||||
type: ClusterIP
|
||||
```
|
||||
|
||||
and defined in `spec.valuesFrom` as a list of `ConfigMap` and `Secret` resources from which to draw values, allowing reusability and/or greater security.
|
||||
See `HelmRelease` CRD [values overrides](https://toolkit.fluxcd.io/components/helm/helmreleases/#values-overrides) documentation for the latest spec.
|
||||
|
||||
## Managing Secrets and ConfigMaps
|
||||
|
||||
You may manage these `ConfigMap` and `Secret` resources any way you wish, but there are several benefits to managing these with the Flux Kustomize Controller.
|
||||
|
||||
It is fairly straigtforward to use Kustomize `configMapGenerator` to [trigger a Helm release upgrade every time the encoded values change](https://toolkit.fluxcd.io/guides/helmreleases/#refer-to-values-in-configmaps-generated-with-kustomize).
|
||||
This common use case currently solveable in Helm by [adding specially crafted annotations](https://helm.sh/docs/howto/charts_tips_and_tricks/#automatically-roll-deployments) to a chart.
|
||||
The Flux Kustomize Controller method allows you to accomplish this on any chart without additional templated annotations.
|
||||
|
||||
You may also use Kustomize Controller built-in [Mozilla SOPS integration](https://toolkit.fluxcd.io/components/kustomize/kustomization/#secrets-decryption) to securely manage your encrypted secrets stored in git.
|
||||
See the [Flux SOPS guide](https://toolkit.fluxcd.io/guides/mozilla-sops/) for step-by-step instructions through various use cases.
|
||||
|
||||
## Automatic Release Upgrades
|
||||
|
||||
If you want Helm Controller to automatically upgrade your releases when a new chart version is available in the release's referenced `HelmRepository`, you may specify a SemVer range (i.e. `>=4.0.0 <5.0.0`) instead of a fixed version.
|
||||
|
||||
This is useful if your release should use a fixed MAJOR chart version, but want the latest MINOR or PATCH versions as they become available.
|
||||
|
||||
For full SemVer range syntax, see `Masterminds/semver` [Checking Version Constraints](https://github.com/Masterminds/semver/blob/master/README.md#checking-version-constraints) documentation.
|
||||
|
||||
## Automatic Uninstalls and Rollback
|
||||
|
||||
The Helm Controller offers an extensive set of configuration options to remediate when a Helm release fails, using [spec.install.remediate](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.InstallRemediation), [spec.upgrade.remediate](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.UpgradeRemediation), [spec.rollback](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.Rollback) and [spec.uninstall](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.Uninstall).
|
||||
Features include the option to remediate with an uninstall after an upgrade failure, and the option to keep a failed release for debugging purposes when it has run out of retries.
|
||||
|
||||
Here is an example for configuring automated uninstalls (for all available fields, consult the `InstallRemediation` and `Uninstall` API references linked above):
|
||||
|
||||
```yaml
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: my-release
|
||||
namespace: default
|
||||
spec:
|
||||
# ...omitted for brevity
|
||||
install:
|
||||
# Remediation configuration for when the Helm install
|
||||
# (or sequent Helm test) action fails
|
||||
remediation:
|
||||
# Number of retries that should be attempted on failures before
|
||||
# bailing, a negative integer equals to unlimited retries
|
||||
retries: -1
|
||||
# Configuration options for the Helm uninstall action
|
||||
uninstall:
|
||||
timeout: 5m
|
||||
disableHooks: false
|
||||
keepHistory: false
|
||||
```
|
||||
|
||||
Here is an example of automated rollback configuration (for all available fields, consult the `UpgradeRemediation` and `Rollback` API references linked above):
|
||||
|
||||
```yaml
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: my-release
|
||||
namespace: default
|
||||
spec:
|
||||
# ...omitted for brevity
|
||||
upgrade:
|
||||
# Remediaton configuration for when an Helm upgrade action fails
|
||||
remediation:
|
||||
# Amount of retries to attempt after a failure,
|
||||
# setting this to 0 means no remedation will be
|
||||
# attempted
|
||||
retries: 5
|
||||
# Configuration options for the Helm rollback action
|
||||
rollback:
|
||||
timeout: 5m
|
||||
disableWait: false
|
||||
disableHooks: false
|
||||
recreate: false
|
||||
force: false
|
||||
cleanupOnFail: false
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Guides > Manage Helm Releases](/guides/helmreleases/)
|
||||
- [Toolkit Components > Helm Controller](/components/helm/controller/)
|
||||
- [Migration > Migrate to the Helm Controller](/guides/helm-operator-migration/)
|
||||
24
go.mod
24
go.mod
@@ -6,17 +6,17 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.1.0
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/fluxcd/go-git-providers v0.0.3
|
||||
github.com/fluxcd/helm-controller/api v0.9.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.8.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.8.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.11.0
|
||||
github.com/fluxcd/notification-controller/api v0.12.0
|
||||
github.com/fluxcd/pkg/apis/meta v0.8.0
|
||||
github.com/fluxcd/pkg/runtime v0.10.1
|
||||
github.com/fluxcd/helm-controller/api v0.10.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.9.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.9.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.11.1
|
||||
github.com/fluxcd/notification-controller/api v0.13.0
|
||||
github.com/fluxcd/pkg/apis/meta v0.9.0
|
||||
github.com/fluxcd/pkg/runtime v0.11.0
|
||||
github.com/fluxcd/pkg/ssh v0.0.5
|
||||
github.com/fluxcd/pkg/untar v0.0.5
|
||||
github.com/fluxcd/pkg/version v0.0.1
|
||||
github.com/fluxcd/source-controller/api v0.11.0
|
||||
github.com/fluxcd/source-controller/api v0.12.0
|
||||
github.com/go-git/go-git/v5 v5.1.0
|
||||
github.com/google/go-containerregistry v0.2.0
|
||||
github.com/manifoldco/promptui v0.7.0
|
||||
@@ -25,11 +25,11 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/xanzy/go-gitlab v0.43.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
|
||||
k8s.io/api v0.20.2
|
||||
k8s.io/apiextensions-apiserver v0.20.2
|
||||
k8s.io/apimachinery v0.20.2
|
||||
k8s.io/api v0.20.4
|
||||
k8s.io/apiextensions-apiserver v0.20.4
|
||||
k8s.io/apimachinery v0.20.4
|
||||
k8s.io/cli-runtime v0.20.2 // indirect
|
||||
k8s.io/client-go v0.20.2
|
||||
k8s.io/client-go v0.20.4
|
||||
sigs.k8s.io/cli-utils v0.22.2
|
||||
sigs.k8s.io/controller-runtime v0.8.3
|
||||
sigs.k8s.io/kustomize/api v0.7.4
|
||||
|
||||
47
go.sum
47
go.sum
@@ -190,30 +190,30 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fluxcd/go-git-providers v0.0.3 h1:pquQvTpd1a4V1efPyZWuVPeIKrTgV8QRoDY0VGH+qiw=
|
||||
github.com/fluxcd/go-git-providers v0.0.3/go.mod h1:iaXf3nEq8MB/LzxfbNcCl48sAtIReUU7jqjJ7CEnfFQ=
|
||||
github.com/fluxcd/helm-controller/api v0.9.0 h1:L60KmCblTQo3UimgCzVQGe330tC+b15CrLozvhPNmJU=
|
||||
github.com/fluxcd/helm-controller/api v0.9.0/go.mod h1:HIWSF3n1QU3hdqjQMFizFUZVr1uV+abmlGAEpB7vB9A=
|
||||
github.com/fluxcd/image-automation-controller/api v0.8.0 h1:lcyoYEQNorNijObqY9ZdSEurt2nXCXgFmx+PcM9W+Dw=
|
||||
github.com/fluxcd/image-automation-controller/api v0.8.0/go.mod h1:7E2dCvoxmTkDttp+Hk8v9eoSK/CdFmFhRKInEXC3yVY=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.8.0 h1:6dTIcyJFApmcmT4HbitWBFvh6ne8jpp8QQseH9Q5hv0=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.8.0/go.mod h1:J18L71jiHYrAu2dg0tgOkOjP+GtQldC1oslhTeX0jqc=
|
||||
github.com/fluxcd/kustomize-controller/api v0.11.0 h1:pPeNh10vzlJQGmAMHLf2lJLVROJah2hu7JeUjjV4+74=
|
||||
github.com/fluxcd/kustomize-controller/api v0.11.0/go.mod h1:uvt/PmSGP/n4SU5mRUa1r7HMwor7ofgBvJV5/rHNB54=
|
||||
github.com/fluxcd/notification-controller/api v0.12.0 h1:yzRnDIdIqT9iV9W0fexJwAROu4ZSNBpKEs5dFf3KaPk=
|
||||
github.com/fluxcd/notification-controller/api v0.12.0/go.mod h1:CA02ixmq+kFN9eBkruvJClkMqffgRjYBMxym3AfhO6c=
|
||||
github.com/fluxcd/helm-controller/api v0.10.0 h1:7z+DvzsTl31cZPAIqlydD6Z5BV9cpgJNQHwycqEri68=
|
||||
github.com/fluxcd/helm-controller/api v0.10.0/go.mod h1:IZ/d5VdxolemPILdN4xeVnHO7kXpUTND/9vJ/rnS/7U=
|
||||
github.com/fluxcd/image-automation-controller/api v0.9.0 h1:LzWN3LwOzX/Q3IOdI6oNLvob+Ne2LDe7POxfiLQg/bs=
|
||||
github.com/fluxcd/image-automation-controller/api v0.9.0/go.mod h1:gpz1FCM/zK4cqvGsyV4OJovFEFLm2lFI7IvJG2BeLgg=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.9.0 h1:RJvzgsQfbHdbQGNjiSrunydAMzFxhc7Erw1vvniSARk=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.9.0/go.mod h1:gFoTJFs977JhE1H6RQSlGwYJGw12aIFDi5ljAn3rtUc=
|
||||
github.com/fluxcd/kustomize-controller/api v0.11.1 h1:seBEImagW+0+AVE4cXQGwJtNH7+26itWNL6VtvU2Sjk=
|
||||
github.com/fluxcd/kustomize-controller/api v0.11.1/go.mod h1:dyRZGTc7ozlf00OhTkB19lbrKv/IjUB8FfBwcV2dO2w=
|
||||
github.com/fluxcd/notification-controller/api v0.13.0 h1:F7G6ktLUvWEi11VqqFtvkpt/dwF+GzSWx6CDTk6/mZU=
|
||||
github.com/fluxcd/notification-controller/api v0.13.0/go.mod h1:0ndWAtU/nlhbiWhOk8ai4/M9q7csjbWVcXcWREs2A10=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.0.1 h1:TkA80R0GopRY27VJqzKyS6ifiKIAfwBd7OHXtV3t2CI=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.0.1/go.mod h1:JAFPfnRmcrAoG1gNiA8kmEXsnOBuDyZ/F5X4DAQcVV0=
|
||||
github.com/fluxcd/pkg/apis/meta v0.8.0 h1:wqWpUsxhKHB1ZztcvOz+vnyhdKW9cWmjFp8Vci/XOdk=
|
||||
github.com/fluxcd/pkg/apis/meta v0.8.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po=
|
||||
github.com/fluxcd/pkg/runtime v0.10.1 h1:NV0pe6lFzodKBIz0dT3xkoR0wJnTCicXwM/v/d5T0+Y=
|
||||
github.com/fluxcd/pkg/runtime v0.10.1/go.mod h1:JD0eZIn5xkTeHHQUWXSqJPIh/ecO0d0qrUKbSVHnpnw=
|
||||
github.com/fluxcd/pkg/apis/meta v0.9.0 h1:rxW69p+VmJCKXXkaRYnovRBFlKjd+MJQfm2RrB0B4j8=
|
||||
github.com/fluxcd/pkg/apis/meta v0.9.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po=
|
||||
github.com/fluxcd/pkg/runtime v0.11.0 h1:FPsiu1k5NQGl2tsaXH5WgSmrOMg7o44jdOP0rW/TI1Y=
|
||||
github.com/fluxcd/pkg/runtime v0.11.0/go.mod h1:ZjAwug6DBLXwo9UdP1/tTPyuWpK9kZ0BEJbctbuEB1o=
|
||||
github.com/fluxcd/pkg/ssh v0.0.5 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A=
|
||||
github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs=
|
||||
github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk=
|
||||
github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw=
|
||||
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.11.0 h1:I2suC+gHB3PuuuHXFeb3RaE9dJeiKew9x02xs9tLmyI=
|
||||
github.com/fluxcd/source-controller/api v0.11.0/go.mod h1:Vuw+7UqEUUOdkKBfTUPHwaQgbn6LL2FwqPDx2UAk7NE=
|
||||
github.com/fluxcd/source-controller/api v0.12.0 h1:ATzWCIXE96Q1iOHElzM0V4xCVEn95QLKpOSmVLiY/lo=
|
||||
github.com/fluxcd/source-controller/api v0.12.0/go.mod h1:+EPyhxC7Y+hUnq7EwAkkLtfbwCxJxF5yfmiyzDk43KY=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
@@ -1133,25 +1133,29 @@ k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
|
||||
k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
|
||||
k8s.io/api v0.18.10/go.mod h1:xWtwPX1v47j5RTncmlMFGCx8b0avh+nP8OgZZ9hjo3M=
|
||||
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
|
||||
k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw=
|
||||
k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8=
|
||||
k8s.io/api v0.20.4 h1:xZjKidCirayzX6tHONRQyTNDVIR55TYVqgATqo6ZULY=
|
||||
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
|
||||
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
|
||||
k8s.io/apiextensions-apiserver v0.18.10/go.mod h1:XOE93YaGrb8Pa+ro00Jx3fhzRJ7UB0bU37jRTQXpTOM=
|
||||
k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
|
||||
k8s.io/apiextensions-apiserver v0.20.2 h1:rfrMWQ87lhd8EzQWRnbQ4gXrniL/yTRBgYH1x1+BLlo=
|
||||
k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs=
|
||||
k8s.io/apiextensions-apiserver v0.20.4 h1:VO/Y5PwBdznMIctX/vvgSNhxffikEmcLC/V1bpbhHhU=
|
||||
k8s.io/apiextensions-apiserver v0.20.4/go.mod h1:Hzebis/9c6Io5yzHp24Vg4XOkTp1ViMwKP/6gmpsfA4=
|
||||
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
||||
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
||||
k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
|
||||
k8s.io/apimachinery v0.18.10/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
|
||||
k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg=
|
||||
k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/apimachinery v0.20.4 h1:vhxQ0PPUUU2Ns1b9r4/UFp13UPs8cw2iOoTjnY9faa0=
|
||||
k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
|
||||
k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
|
||||
k8s.io/apiserver v0.18.10/go.mod h1:N4FaJo9BeSgmtvVByXi4fPSQPRqhvvLMGqswwkddob8=
|
||||
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
|
||||
k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA=
|
||||
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
|
||||
k8s.io/cli-runtime v0.18.10/go.mod h1:8awhtXxYzOsxCrxgMTmR3DkIV8M/Gcu/v1aCIzQKIV4=
|
||||
k8s.io/cli-runtime v0.20.2 h1:W0/FHdbApnl9oB7xdG643c/Zaf7TZT+43I+zKxwqvhU=
|
||||
k8s.io/cli-runtime v0.20.2/go.mod h1:FjH6uIZZZP3XmwrXWeeYCbgxcrD6YXxoAykBaWH0VdM=
|
||||
@@ -1160,19 +1164,22 @@ k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
|
||||
k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
|
||||
k8s.io/client-go v0.18.10/go.mod h1:XBkFAqPrzqfwmGkV5ac+mlgBpWcz5TkhLw2808q8C3c=
|
||||
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
|
||||
k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ=
|
||||
k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE=
|
||||
k8s.io/client-go v0.20.4 h1:85crgh1IotNkLpKYKZHVNI1JT86nr/iDCvq2iWKsql4=
|
||||
k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
|
||||
k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs=
|
||||
k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
|
||||
k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
||||
k8s.io/code-generator v0.18.10/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
||||
k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
|
||||
k8s.io/code-generator v0.20.2/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
|
||||
k8s.io/code-generator v0.20.4/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
|
||||
k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
|
||||
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
|
||||
k8s.io/component-base v0.18.10/go.mod h1:ZzFXjzUBHKOcF0mnWkxBI1wDu5t+CV3GxXKKvHZBLf0=
|
||||
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
|
||||
k8s.io/component-base v0.20.2/go.mod h1:pzFtCiwe/ASD0iV7ySMu8SYVJjCapNM9bjvk7ptpKh0=
|
||||
k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
|
||||
k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
|
||||
@@ -207,7 +207,7 @@ verify_binary() {
|
||||
setup_binary() {
|
||||
chmod 755 "${TMP_BIN}"
|
||||
info "Installing flux to ${BIN_DIR}/flux"
|
||||
tar -xzf "${TMP_BIN}" -C "${TMP_DIR}"
|
||||
tar -xzof "${TMP_BIN}" -C "${TMP_DIR}"
|
||||
|
||||
local CMD_MOVE="mv -f \"${TMP_DIR}/flux\" \"${BIN_DIR}\""
|
||||
if [[ -w "${BIN_DIR}" ]]; then
|
||||
|
||||
@@ -19,6 +19,8 @@ package bootstrap
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -29,6 +31,7 @@ import (
|
||||
"sigs.k8s.io/cli-utils/pkg/object"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
@@ -152,10 +155,48 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
||||
|
||||
// Conditionally install manifests
|
||||
if mustInstallManifests(ctx, b.kube, options.Namespace) {
|
||||
b.logger.Actionf("installing components in %q namespace", options.Namespace)
|
||||
kubectlArgs := []string{"apply", "-f", filepath.Join(b.git.Path(), manifests.Path)}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
return err
|
||||
componentsYAML := filepath.Join(b.git.Path(), manifests.Path)
|
||||
|
||||
// Apply components using any existing customisations
|
||||
kfile := filepath.Join(filepath.Dir(componentsYAML), konfig.DefaultKustomizationFileName())
|
||||
if _, err := os.Stat(kfile); err == nil {
|
||||
tmpDir, err := ioutil.TempDir("", "gotk-crds")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Extract the CRDs from the components manifest
|
||||
crdsYAML := filepath.Join(tmpDir, "gotk-crds.yaml")
|
||||
if err := utils.ExtractCRDs(componentsYAML, crdsYAML); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Apply the CRDs
|
||||
b.logger.Actionf("installing toolkit.fluxcd.io CRDs")
|
||||
kubectlArgs := []string{"apply", "-f", crdsYAML}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for CRDs to be established
|
||||
b.logger.Waitingf("waiting for CRDs to be reconciled")
|
||||
kubectlArgs = []string{"wait", "--for", "condition=established", "-f", crdsYAML}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
b.logger.Successf("CRDs reconciled successfully")
|
||||
|
||||
// Apply the components and their patches
|
||||
b.logger.Actionf("installing components in %q namespace", options.Namespace)
|
||||
kubectlArgs = []string{"apply", "-k", filepath.Dir(componentsYAML)}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Apply the CRDs and controllers
|
||||
b.logger.Actionf("installing components in %q namespace", options.Namespace)
|
||||
kubectlArgs := []string{"apply", "-f", componentsYAML}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
b.logger.Successf("installed components")
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ type GitProviderBootstrapper struct {
|
||||
defaultBranch string
|
||||
visibility string
|
||||
|
||||
reconcile bool
|
||||
|
||||
teams map[string]string
|
||||
|
||||
readWriteKey bool
|
||||
@@ -168,6 +170,16 @@ func (o sshHostnameOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
b.sshHostname = string(o)
|
||||
}
|
||||
|
||||
func WithReconcile() GitProviderOption {
|
||||
return reconcileOption(true)
|
||||
}
|
||||
|
||||
type reconcileOption bool
|
||||
|
||||
func (o reconcileOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
b.reconcile = true
|
||||
}
|
||||
|
||||
func (b *GitProviderBootstrapper) ReconcileSyncConfig(ctx context.Context, options sync.Options) error {
|
||||
repo, err := b.getRepository(ctx)
|
||||
if err != nil {
|
||||
@@ -268,29 +280,28 @@ func (b *GitProviderBootstrapper) reconcileOrgRepository(ctx context.Context) (g
|
||||
}
|
||||
// go-git-providers has at present some issues with the idempotency
|
||||
// of the available Reconcile methods, and setting e.g. the default
|
||||
// branch correctly. Resort to Create with AutoInit until this has
|
||||
// been resolved.
|
||||
repo, err = b.provider.OrgRepositories().Create(ctx, repoRef, repoInfo, &gitprovider.RepositoryCreateOptions{
|
||||
AutoInit: gitprovider.BoolVar(true),
|
||||
})
|
||||
// branch correctly. Resort to Create until this has been resolved.
|
||||
repo, err = b.provider.OrgRepositories().Create(ctx, repoRef, repoInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create new Git repository %q: %w", repoRef.String(), err)
|
||||
}
|
||||
b.logger.Successf("repository %q created", repoRef.String())
|
||||
}
|
||||
|
||||
// Set default branch before calling Reconcile due to bug described
|
||||
// above.
|
||||
repoInfo.DefaultBranch = repo.Get().DefaultBranch
|
||||
var changed bool
|
||||
if err = retry(1, 2*time.Second, func() (err error) {
|
||||
repo, changed, err = b.provider.OrgRepositories().Reconcile(ctx, repoRef, repoInfo)
|
||||
return
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err)
|
||||
}
|
||||
if changed {
|
||||
b.logger.Successf("repository %q reconciled", repoRef.String())
|
||||
if b.reconcile {
|
||||
// Set default branch before calling Reconcile due to bug described
|
||||
// above.
|
||||
repoInfo.DefaultBranch = repo.Get().DefaultBranch
|
||||
if err = retry(1, 2*time.Second, func() (err error) {
|
||||
repo, changed, err = b.provider.OrgRepositories().Reconcile(ctx, repoRef, repoInfo)
|
||||
return
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err)
|
||||
}
|
||||
if changed {
|
||||
b.logger.Successf("repository %q reconciled", repoRef.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Build the team access config
|
||||
@@ -310,9 +321,8 @@ func (b *GitProviderBootstrapper) reconcileOrgRepository(ctx context.Context) (g
|
||||
_, changed, err = repo.TeamAccess().Reconcile(ctx, i)
|
||||
if err != nil {
|
||||
warning = fmt.Errorf("failed to grant permissions to team: %w", ErrReconciledWithWarning)
|
||||
b.logger.Failuref("failed to grant %q permissions to %q: %w", *i.Permission, i.Name, err)
|
||||
}
|
||||
if changed {
|
||||
b.logger.Failuref("failed to grant %q permissions to %q: %s", *i.Permission, i.Name, err.Error())
|
||||
} else if changed {
|
||||
b.logger.Successf("granted %q permissions to %q", *i.Permission, i.Name)
|
||||
}
|
||||
}
|
||||
@@ -334,6 +344,7 @@ func (b *GitProviderBootstrapper) reconcileUserRepository(ctx context.Context) (
|
||||
repoRef := newUserRepositoryRef(userRef, repoName)
|
||||
repoInfo := newRepositoryInfo(b.description, b.defaultBranch, b.visibility)
|
||||
|
||||
// Reconcile the user repository
|
||||
repo, err := b.provider.UserRepositories().Get(ctx, repoRef)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gitprovider.ErrNotFound) {
|
||||
@@ -341,29 +352,28 @@ func (b *GitProviderBootstrapper) reconcileUserRepository(ctx context.Context) (
|
||||
}
|
||||
// go-git-providers has at present some issues with the idempotency
|
||||
// of the available Reconcile methods, and setting e.g. the default
|
||||
// branch correctly. Resort to Create with AutoInit until this has
|
||||
// been resolved.
|
||||
repo, err = b.provider.UserRepositories().Create(ctx, repoRef, repoInfo, &gitprovider.RepositoryCreateOptions{
|
||||
AutoInit: gitprovider.BoolVar(true),
|
||||
})
|
||||
// branch correctly. Resort to Create until this has been resolved.
|
||||
repo, err = b.provider.UserRepositories().Create(ctx, repoRef, repoInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create new Git repository %q: %w", repoRef.String(), err)
|
||||
}
|
||||
b.logger.Successf("repository %q created", repoRef.String())
|
||||
}
|
||||
|
||||
// Set default branch before calling Reconcile due to bug described
|
||||
// above.
|
||||
repoInfo.DefaultBranch = repo.Get().DefaultBranch
|
||||
var changed bool
|
||||
if err = retry(1, 2*time.Second, func() (err error) {
|
||||
repo, changed, err = b.provider.UserRepositories().Reconcile(ctx, repoRef, repoInfo)
|
||||
return
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err)
|
||||
}
|
||||
if changed {
|
||||
b.logger.Successf("repository %q reconciled", repoRef.String())
|
||||
if b.reconcile {
|
||||
// Set default branch before calling Reconcile due to bug described
|
||||
// above.
|
||||
repoInfo.DefaultBranch = repo.Get().DefaultBranch
|
||||
var changed bool
|
||||
if err = retry(1, 2*time.Second, func() (err error) {
|
||||
repo, changed, err = b.provider.UserRepositories().Reconcile(ctx, repoRef, repoInfo)
|
||||
return
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err)
|
||||
}
|
||||
if changed {
|
||||
b.logger.Successf("repository %q reconciled", repoRef.String())
|
||||
}
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -29,24 +30,28 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
imageautov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
||||
imagereflectv1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
"github.com/fluxcd/pkg/runtime/dependency"
|
||||
"github.com/fluxcd/pkg/version"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
sigyaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
imageautov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||
imagereflectv1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
"github.com/fluxcd/pkg/runtime/dependency"
|
||||
"github.com/fluxcd/pkg/version"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
)
|
||||
@@ -313,3 +318,41 @@ func CompatibleVersion(binary, target string) bool {
|
||||
}
|
||||
return binSv.Major() == targetSv.Major() && binSv.Minor() == targetSv.Minor()
|
||||
}
|
||||
|
||||
func ExtractCRDs(inManifestPath, outManifestPath string) error {
|
||||
manifests, err := ioutil.ReadFile(inManifestPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
crds := ""
|
||||
reader := sigyaml.NewYAMLOrJSONDecoder(bytes.NewReader(manifests), 2048)
|
||||
|
||||
for {
|
||||
var obj unstructured.Unstructured
|
||||
err := reader.Decode(&obj)
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if obj.GetKind() == "CustomResourceDefinition" {
|
||||
b, err := obj.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
y, err := yaml.JSONToYAML(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
crds += "---\n" + string(y)
|
||||
}
|
||||
}
|
||||
|
||||
if crds == "" {
|
||||
return fmt.Errorf("no CRDs found in %s", inManifestPath)
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(outManifestPath, []byte(crds), os.ModePerm)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.9.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.9.0/helm-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.10.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.10.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/image-automation-controller/releases/download/v0.8.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.8.0/image-automation-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.9.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.9.0/image-automation-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.8.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.8.0/image-reflector-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.9.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.9.0/image-reflector-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.11.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.11.0/kustomize-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.11.1/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.11.1/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.12.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.12.0/notification-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.13.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.13.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.11.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.11.0/source-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.12.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.12.0/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/kustomize-controller/releases/download/v0.11.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.11.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.9.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.12.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.8.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.8.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.12.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.11.1/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.10.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.13.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.9.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.9.0/image-automation-controller.crds.yaml
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: deny-ingress
|
||||
name: allow-egress
|
||||
spec:
|
||||
policyTypes:
|
||||
- Ingress
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- deny-ingress.yaml
|
||||
- allow-egress.yaml
|
||||
- allow-scraping.yaml
|
||||
- allow-webhooks.yaml
|
||||
|
||||
@@ -66,6 +66,8 @@ nav:
|
||||
- Sortable image tags to use with automation: guides/sortable-image-tags.md
|
||||
- Use Cases:
|
||||
- Azure: use-cases/azure.md
|
||||
- GitHub Actions Manifest Generation: use-cases/gh-actions-manifest-generation.md
|
||||
- Helm: use-cases/helm.md
|
||||
- Toolkit Components:
|
||||
- Overview: components/index.md
|
||||
- Source Controller:
|
||||
@@ -147,6 +149,7 @@ nav:
|
||||
- Export image repository: cmd/flux_export_image_repository.md
|
||||
- Export image update: cmd/flux_export_image_update.md
|
||||
- Get: cmd/flux_get.md
|
||||
- Get all: cmd/flux_get_all.md
|
||||
- Get kustomizations: cmd/flux_get_kustomizations.md
|
||||
- Get helmreleases: cmd/flux_get_helmreleases.md
|
||||
- Get sources: cmd/flux_get_sources.md
|
||||
|
||||
@@ -41,10 +41,10 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
|
||||
var keypair *ssh.KeyPair
|
||||
switch {
|
||||
case options.Username != "", options.Password != "":
|
||||
case options.Username != "" && options.Password != "":
|
||||
// noop
|
||||
case len(options.PrivateKeyPath) > 0:
|
||||
if keypair, err = loadKeyPair(options.PrivateKeyPath); err != nil {
|
||||
if keypair, err = loadKeyPair(options.PrivateKeyPath, options.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case len(options.PrivateKeyAlgorithm) > 0:
|
||||
@@ -101,7 +101,7 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile []byte
|
||||
secret.Labels = options.Labels
|
||||
secret.StringData = map[string]string{}
|
||||
|
||||
if options.Username != "" || options.Password != "" {
|
||||
if options.Username != "" && options.Password != "" {
|
||||
secret.StringData[UsernameSecretKey] = options.Username
|
||||
secret.StringData[PasswordSecretKey] = options.Password
|
||||
}
|
||||
@@ -119,18 +119,28 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile []byte
|
||||
secret.StringData[PrivateKeySecretKey] = string(keypair.PrivateKey)
|
||||
secret.StringData[PublicKeySecretKey] = string(keypair.PublicKey)
|
||||
secret.StringData[KnownHostsSecretKey] = string(hostKey)
|
||||
// set password if present
|
||||
if options.Password != "" {
|
||||
secret.StringData[PasswordSecretKey] = string(options.Password)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func loadKeyPair(path string) (*ssh.KeyPair, error) {
|
||||
func loadKeyPair(path string, password string) (*ssh.KeyPair, error) {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open private key file: %w", err)
|
||||
}
|
||||
|
||||
ppk, err := cryptssh.ParsePrivateKey(b)
|
||||
var ppk cryptssh.Signer
|
||||
if password != "" {
|
||||
ppk, err = cryptssh.ParsePrivateKeyWithPassphrase(b, []byte(password))
|
||||
} else {
|
||||
ppk, err = cryptssh.ParsePrivateKey(b)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -18,23 +18,82 @@ package sourcesecret
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/testdata"
|
||||
)
|
||||
|
||||
func Test_loadKeyPair(t *testing.T) {
|
||||
pk, _ := ioutil.ReadFile("testdata/rsa")
|
||||
ppk, _ := ioutil.ReadFile("testdata/rsa.pub")
|
||||
func Test_passwordLoadKeyPair(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
privateKeyPath string
|
||||
publicKeyPath string
|
||||
password string
|
||||
}{
|
||||
{
|
||||
name: "private key pair with password",
|
||||
privateKeyPath: "testdata/password_rsa",
|
||||
publicKeyPath: "testdata/password_rsa.pub",
|
||||
password: "password",
|
||||
},
|
||||
}
|
||||
|
||||
got, err := loadKeyPair("testdata/rsa")
|
||||
if err != nil {
|
||||
t.Errorf("loadKeyPair() error = %v", err)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got.PrivateKey, pk) {
|
||||
t.Errorf("PrivateKey %s != %s", got.PrivateKey, pk)
|
||||
}
|
||||
if !reflect.DeepEqual(got.PublicKey, ppk) {
|
||||
t.Errorf("PublicKey %s != %s", got.PublicKey, ppk)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
pk, _ := ioutil.ReadFile(tt.privateKeyPath)
|
||||
ppk, _ := ioutil.ReadFile(tt.publicKeyPath)
|
||||
|
||||
got, err := loadKeyPair(tt.privateKeyPath, tt.password)
|
||||
if err != nil {
|
||||
t.Errorf("loadKeyPair() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.PrivateKey, pk) {
|
||||
t.Errorf("PrivateKey %s != %s", got.PrivateKey, pk)
|
||||
}
|
||||
if !reflect.DeepEqual(got.PublicKey, ppk) {
|
||||
t.Errorf("PublicKey %s != %s", got.PublicKey, ppk)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_PasswordlessLoadKeyPair(t *testing.T) {
|
||||
for algo, privateKey := range testdata.PEMBytes {
|
||||
t.Run(algo, func(t *testing.T) {
|
||||
f, err := ioutil.TempFile("", "test-private-key-")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create temporary file. err: %s", err)
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
if _, err = f.Write(privateKey); err != nil {
|
||||
t.Fatalf("unable to write private key to file. err: %s", err)
|
||||
}
|
||||
|
||||
got, err := loadKeyPair(f.Name(), "")
|
||||
if err != nil {
|
||||
t.Errorf("loadKeyPair() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
pk, _ := ioutil.ReadFile(f.Name())
|
||||
if !reflect.DeepEqual(got.PrivateKey, pk) {
|
||||
t.Errorf("PrivateKey %s != %s", got.PrivateKey, string(privateKey))
|
||||
}
|
||||
|
||||
signer, err := ssh.ParsePrivateKey(privateKey)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got.PublicKey, ssh.MarshalAuthorizedKey(signer.PublicKey())) {
|
||||
t.Errorf("PublicKey %s != %s", got.PublicKey, ssh.MarshalAuthorizedKey(signer.PublicKey()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
17
pkg/manifestgen/sourcesecret/testdata/password_rsa
vendored
Normal file
17
pkg/manifestgen/sourcesecret/testdata/password_rsa
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB18lOcbN
|
||||
Q7pk768hyQUymCAAAAEAAAAAEAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQCi/p5KtpRl
|
||||
tu3yxEsc+NtR9kRBuYhsh55609dNiTonLlL7K00pLCEWrtEIVM7FzD8IA6Q1NMNBFijje3
|
||||
6gnqMlo6M/cJObkGfZFC025diLI5/ND5R/l60XLtRZfh92K9nCsQKsJaW+R8LTtBdhil/q
|
||||
M/+u07sFHzzk6/36FStg/QAAAiAQAjBJ6TYZuu4iHrrQgbhmlQem18Xjm8f2M9M0BrYgJV
|
||||
F5OVL7mL/bsFTp0IA92HXnxGs0gF4ue5ujCE7SWOyr4SpJfgijExnmDPkZ9nhCG06MsCQ9
|
||||
uU7tTtEnrYcZ5/mmEe8E/O74Mo8xBqI8Unv95eF4p/tAMcDctVX39/lSjP1UZYL6vrLk2L
|
||||
SoEWK2DmZ2ZYdtBJ20AGDJ7MRIX3X/+qZkuYcy7GfPTuDKPIyrr7UEIYH//x8RaGuvOUuu
|
||||
P5bXGOBCTayZgGeWwNDePVITxMhpqTYjy7hqJ1ppBEv1svvbax5ksbwTRzU6quN75o+tbX
|
||||
hf5v0HbiRl3w6LtuwciiQtGsgijxt1noViZvpMLam5EJ3+eTnKnfEPxBMaCx7qepqPT9yI
|
||||
GJ/myyB/+FMkVe9epBeO2wyBTPPzr9O8co8SbcFkFEpcmxKk8toPf4F4XGs7lnibsDXGWE
|
||||
s2+WPmf17WLgpTMLutSVFIxw/V6ajnVrTTTE9AOwC9TYBx152YTWGILUlMMQ4AdNri8H80
|
||||
k/RMv18Tut6k4v6I1aKfUSfXRaaxwagt6zMJ2TvYJFsskfTboM/FjzcDvl4jWQvfcoKJJa
|
||||
da6L6TwnfL03qI+tdT84R4a9oYgZ27WB0ekPnmDpWgIl5jN/F2mHz2/KpuAzC7JgpPdzty
|
||||
271M16OmGvgerrvc/57d0bh4x/E9gj3ZMpkoXBH/lfs5c7LbvRxQ
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
1
pkg/manifestgen/sourcesecret/testdata/password_rsa.pub
vendored
Normal file
1
pkg/manifestgen/sourcesecret/testdata/password_rsa.pub
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCi/p5KtpRltu3yxEsc+NtR9kRBuYhsh55609dNiTonLlL7K00pLCEWrtEIVM7FzD8IA6Q1NMNBFijje36gnqMlo6M/cJObkGfZFC025diLI5/ND5R/l60XLtRZfh92K9nCsQKsJaW+R8LTtBdhil/qM/+u07sFHzzk6/36FStg/Q==
|
||||
Reference in New Issue
Block a user