Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd34870334 | ||
|
|
a56ce1f867 | ||
|
|
dab5bbd393 | ||
|
|
15ebfd7eb6 | ||
|
|
5ab8dd2557 | ||
|
|
9164914d16 | ||
|
|
c9e0bc0807 | ||
|
|
61439adf9b | ||
|
|
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 | ||
|
|
40ce3d50c2 | ||
|
|
68046067c5 | ||
|
|
e3b12a8a24 | ||
|
|
f123b9d3cb |
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
|
# image-*-controller CRDs; these use the same API group
|
||||||
IMG_REFL_VER=$(controller_version image-reflector-controller)
|
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/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/v1alpha2/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/imagepolicies.md" > docs/components/image/imagepolicies.md
|
||||||
|
|
||||||
IMG_AUTO_VER=$(controller_version image-automation-controller)
|
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/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
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
11
.github/workflows/release.yaml
vendored
11
.github/workflows/release.yaml
vendored
@@ -53,6 +53,17 @@ jobs:
|
|||||||
make cmd/flux/manifests
|
make cmd/flux/manifests
|
||||||
./manifests/scripts/bundle.sh "" ./output manifests.tar.gz
|
./manifests/scripts/bundle.sh "" ./output manifests.tar.gz
|
||||||
kustomize build ./manifests/install > ./output/install.yaml
|
kustomize build ./manifests/install > ./output/install.yaml
|
||||||
|
- name: Build CRDs
|
||||||
|
run: |
|
||||||
|
kustomize build manifests/crds > all-crds.yaml
|
||||||
|
- name: Generate OpenAPI JSON schemas from CRDs
|
||||||
|
uses: fluxcd/pkg//actions/crdjsonschema@main
|
||||||
|
with:
|
||||||
|
crd: all-crds.yaml
|
||||||
|
output: schemas
|
||||||
|
- name: Archive the OpenAPI JSON schemas
|
||||||
|
run: |
|
||||||
|
tar -czvf ./output/crd-schemas.tar.gz -C schemas .
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v1
|
uses: goreleaser/goreleaser-action@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
65
.github/workflows/update.yaml
vendored
65
.github/workflows/update.yaml
vendored
@@ -23,20 +23,32 @@ jobs:
|
|||||||
PR_BODY=""
|
PR_BODY=""
|
||||||
|
|
||||||
bump_version() {
|
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 LATEST_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 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
|
local changed=false
|
||||||
# bump kustomize
|
|
||||||
sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${RELEASE_VERSION}\2/g" "manifests/bases/$1/kustomization.yaml"
|
|
||||||
|
|
||||||
if [[ ! -z $(grep "github.com/fluxcd/$1/api" go.mod | awk '{print $2}') ]]; then
|
if [[ "${CTRL_VERSION}" != "${LATEST_VERSION}" ]]; then
|
||||||
# bump go mod
|
sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${LATEST_VERSION}\2/g" "manifests/bases/$1/kustomization.yaml"
|
||||||
go mod edit -require="github.com/fluxcd/$1/api@${RELEASE_VERSION}"
|
changed=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# NB: special URL encoded formatting required for newlines
|
if [[ "${CRD_VERSION}" != "${LATEST_VERSION}" ]]; then
|
||||||
PR_BODY="$PR_BODY- $1 to ${RELEASE_VERSION}%0A https://github.com/fluxcd/$1/blob/${RELEASE_VERSION}/CHANGELOG.md%0A"
|
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}"
|
||||||
|
rm go.sum
|
||||||
|
go mod tidy
|
||||||
|
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
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,9 +61,6 @@ jobs:
|
|||||||
bump_version image-reflector-controller
|
bump_version image-reflector-controller
|
||||||
bump_version image-automation-controller
|
bump_version image-automation-controller
|
||||||
|
|
||||||
# add missing and remove unused modules
|
|
||||||
go mod tidy
|
|
||||||
|
|
||||||
# diff change
|
# diff change
|
||||||
git diff
|
git diff
|
||||||
|
|
||||||
@@ -63,21 +72,21 @@ jobs:
|
|||||||
id: cpr
|
id: cpr
|
||||||
uses: peter-evans/create-pull-request@v3
|
uses: peter-evans/create-pull-request@v3
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||||
commit-message: |
|
commit-message: |
|
||||||
Update toolkit components
|
Update toolkit components
|
||||||
|
|
||||||
${{ steps.update.outputs.pr_body }}
|
${{ steps.update.outputs.pr_body }}
|
||||||
committer: GitHub <noreply@github.com>
|
committer: GitHub <noreply@github.com>
|
||||||
author: fluxcdbot <fluxcdbot@users.noreply.github.com>
|
author: fluxcdbot <fluxcdbot@users.noreply.github.com>
|
||||||
signoff: true
|
signoff: true
|
||||||
branch: update-components
|
branch: update-components
|
||||||
title: Update toolkit components
|
title: Update toolkit components
|
||||||
body: |
|
body: |
|
||||||
${{ steps.update.outputs.pr_body }}
|
${{ steps.update.outputs.pr_body }}
|
||||||
labels: |
|
labels: |
|
||||||
area/build
|
area/build
|
||||||
reviewers: ${{ secrets.ASSIGNEES }}
|
reviewers: ${{ secrets.ASSIGNEES }}
|
||||||
|
|
||||||
- name: Check output
|
- name: Check output
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ publishers:
|
|||||||
.github/aur/flux-go/publish.sh {{ .Version }}
|
.github/aur/flux-go/publish.sh {{ .Version }}
|
||||||
release:
|
release:
|
||||||
extra_files:
|
extra_files:
|
||||||
|
- glob: ./output/crd-schemas.tar.gz
|
||||||
- glob: ./output/manifests.tar.gz
|
- glob: ./output/manifests.tar.gz
|
||||||
- glob: ./output/install.yaml
|
- glob: ./output/install.yaml
|
||||||
dockers:
|
dockers:
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ command will perform an upgrade if needed.`,
|
|||||||
|
|
||||||
# Run bootstrap for a Git repository with a passwordless private key
|
# 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>
|
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,
|
RunE: bootstrapGitCmdRun,
|
||||||
}
|
}
|
||||||
@@ -163,6 +166,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
repositoryURL.Host = repositoryURL.Hostname()
|
repositoryURL.Host = repositoryURL.Hostname()
|
||||||
} else {
|
} else {
|
||||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
||||||
|
secretOpts.Password = gitArgs.password
|
||||||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||||
secretOpts.ECDSACurve = bootstrapArgs.keyECDSACurve.Curve
|
secretOpts.ECDSACurve = bootstrapArgs.keyECDSACurve.Curve
|
||||||
|
|
||||||
@@ -189,7 +193,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
URL: repositoryURL.String(),
|
URL: repositoryURL.String(),
|
||||||
Branch: bootstrapArgs.branch,
|
Branch: bootstrapArgs.branch,
|
||||||
Secret: bootstrapArgs.secretName,
|
Secret: bootstrapArgs.secretName,
|
||||||
TargetPath: gitArgs.path.String(),
|
TargetPath: gitArgs.path.ToSlash(),
|
||||||
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
ManifestFile: sync.MakeDefaultOptions().ManifestFile,
|
||||||
GitImplementation: sourceGitArgs.gitImplementation.String(),
|
GitImplementation: sourceGitArgs.gitImplementation.String(),
|
||||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||||
@@ -229,7 +233,7 @@ func transportForURL(u *url.URL) (transport.AuthMethod, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
case "ssh":
|
case "ssh":
|
||||||
if bootstrapArgs.privateKeyFile != "" {
|
if bootstrapArgs.privateKeyFile != "" {
|
||||||
return ssh.NewPublicKeysFromFile(u.User.Username(), bootstrapArgs.privateKeyFile, "")
|
return ssh.NewPublicKeysFromFile(u.User.Username(), bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ type githubFlags struct {
|
|||||||
path flags.SafeRelativePath
|
path flags.SafeRelativePath
|
||||||
teams []string
|
teams []string
|
||||||
readWriteKey bool
|
readWriteKey bool
|
||||||
|
reconcile bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -95,11 +96,12 @@ func init() {
|
|||||||
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.repository, "repository", "", "GitHub repository name")
|
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.repository, "repository", "", "GitHub repository name")
|
||||||
bootstrapGitHubCmd.Flags().StringArrayVar(&githubArgs.teams, "team", []string{}, "GitHub team to be given maintainer access")
|
bootstrapGitHubCmd.Flags().StringArrayVar(&githubArgs.teams, "team", []string{}, "GitHub team to be given maintainer access")
|
||||||
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.personal, "personal", false, "if true, the owner is assumed to be a GitHub user; otherwise an org")
|
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.personal, "personal", false, "if true, the owner is assumed to be a GitHub user; otherwise an org")
|
||||||
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.private, "private", true, "if true, the repository is assumed to be private")
|
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.private, "private", true, "if true, the repository is setup or configured as private")
|
||||||
bootstrapGitHubCmd.Flags().DurationVar(&githubArgs.interval, "interval", time.Minute, "sync interval")
|
bootstrapGitHubCmd.Flags().DurationVar(&githubArgs.interval, "interval", time.Minute, "sync interval")
|
||||||
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.hostname, "hostname", ghDefaultDomain, "GitHub hostname")
|
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().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.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)
|
bootstrapCmd.AddCommand(bootstrapGitHubCmd)
|
||||||
}
|
}
|
||||||
@@ -235,6 +237,9 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
if !githubArgs.private {
|
if !githubArgs.private {
|
||||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public"))
|
bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public"))
|
||||||
}
|
}
|
||||||
|
if githubArgs.reconcile {
|
||||||
|
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||||
|
}
|
||||||
|
|
||||||
// Setup bootstrapper with constructed configs
|
// Setup bootstrapper with constructed configs
|
||||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ type gitlabFlags struct {
|
|||||||
path flags.SafeRelativePath
|
path flags.SafeRelativePath
|
||||||
teams []string
|
teams []string
|
||||||
readWriteKey bool
|
readWriteKey bool
|
||||||
|
reconcile bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var gitlabArgs gitlabFlags
|
var gitlabArgs gitlabFlags
|
||||||
@@ -95,11 +96,12 @@ func init() {
|
|||||||
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.repository, "repository", "", "GitLab repository name")
|
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.repository, "repository", "", "GitLab repository name")
|
||||||
bootstrapGitLabCmd.Flags().StringArrayVar(&gitlabArgs.teams, "team", []string{}, "GitLab teams to be given maintainer access")
|
bootstrapGitLabCmd.Flags().StringArrayVar(&gitlabArgs.teams, "team", []string{}, "GitLab teams to be given maintainer access")
|
||||||
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.personal, "personal", false, "if true, the owner is assumed to be a GitLab user; otherwise a group")
|
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.personal, "personal", false, "if true, the owner is assumed to be a GitLab user; otherwise a group")
|
||||||
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.private, "private", true, "if true, the repository is assumed to be private")
|
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.private, "private", true, "if true, the repository is setup or configured as private")
|
||||||
bootstrapGitLabCmd.Flags().DurationVar(&gitlabArgs.interval, "interval", time.Minute, "sync interval")
|
bootstrapGitLabCmd.Flags().DurationVar(&gitlabArgs.interval, "interval", time.Minute, "sync interval")
|
||||||
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.hostname, "hostname", glDefaultDomain, "GitLab hostname")
|
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().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.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)
|
bootstrapCmd.AddCommand(bootstrapGitLabCmd)
|
||||||
}
|
}
|
||||||
@@ -251,6 +253,9 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
if !gitlabArgs.private {
|
if !gitlabArgs.private {
|
||||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public"))
|
bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public"))
|
||||||
}
|
}
|
||||||
|
if gitlabArgs.reconcile {
|
||||||
|
bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile())
|
||||||
|
}
|
||||||
|
|
||||||
// Setup bootstrapper with constructed configs
|
// Setup bootstrapper with constructed configs
|
||||||
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...)
|
||||||
|
|||||||
@@ -74,14 +74,15 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
eventSources := []notificationv1.CrossNamespaceObjectReference{}
|
eventSources := []notificationv1.CrossNamespaceObjectReference{}
|
||||||
for _, eventSource := range alertArgs.eventSources {
|
for _, eventSource := range alertArgs.eventSources {
|
||||||
kind, name := utils.ParseObjectKindName(eventSource)
|
kind, name, namespace := utils.ParseObjectKindNameNamespace(eventSource)
|
||||||
if kind == "" {
|
if kind == "" {
|
||||||
return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", eventSource)
|
return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", eventSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
eventSources = append(eventSources, notificationv1.CrossNamespaceObjectReference{
|
eventSources = append(eventSources, notificationv1.CrossNamespaceObjectReference{
|
||||||
Kind: kind,
|
Kind: kind,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,9 +113,10 @@ type helmReleaseFlags struct {
|
|||||||
chart string
|
chart string
|
||||||
chartVersion string
|
chartVersion string
|
||||||
targetNamespace string
|
targetNamespace string
|
||||||
valuesFile []string
|
valuesFiles []string
|
||||||
valuesFrom flags.HelmReleaseValuesFrom
|
valuesFrom flags.HelmReleaseValuesFrom
|
||||||
saName string
|
saName string
|
||||||
|
crds flags.CRDsPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
var helmReleaseArgs helmReleaseFlags
|
var helmReleaseArgs helmReleaseFlags
|
||||||
@@ -128,8 +129,9 @@ 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().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.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().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())
|
createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.valuesFrom, "values-from", helmReleaseArgs.valuesFrom.Description())
|
||||||
|
createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.crds, "crds", helmReleaseArgs.crds.Description())
|
||||||
createCmd.AddCommand(createHelmReleaseCmd)
|
createCmd.AddCommand(createHelmReleaseCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,9 +186,14 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
helmRelease.Spec.ServiceAccountName = helmReleaseArgs.saName
|
helmRelease.Spec.ServiceAccountName = helmReleaseArgs.saName
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(helmReleaseArgs.valuesFile) > 0 {
|
if helmReleaseArgs.crds != "" {
|
||||||
var valuesMap map[string]interface{}
|
helmRelease.Spec.Install = &helmv2.Install{CRDs: helmv2.Create}
|
||||||
for _, v := range helmReleaseArgs.valuesFile {
|
helmRelease.Spec.Upgrade = &helmv2.Upgrade{CRDs: helmv2.CRDsPolicy(helmReleaseArgs.crds.String())}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(helmReleaseArgs.valuesFiles) > 0 {
|
||||||
|
valuesMap := make(map[string]interface{})
|
||||||
|
for _, v := range helmReleaseArgs.valuesFiles {
|
||||||
data, err := ioutil.ReadFile(v)
|
data, err := ioutil.ReadFile(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading values from %s failed: %w", v, err)
|
return fmt.Errorf("reading values from %s failed: %w", v, err)
|
||||||
@@ -202,11 +209,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("unmarshaling values from %s failed: %w", v, err)
|
return fmt.Errorf("unmarshaling values from %s failed: %w", v, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if valuesMap == nil {
|
valuesMap = transform.MergeMaps(valuesMap, jsonMap)
|
||||||
valuesMap = jsonMap
|
|
||||||
} else {
|
|
||||||
valuesMap = transform.MergeMaps(valuesMap, jsonMap)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonRaw, err := json.Marshal(valuesMap)
|
jsonRaw, err := json.Marshal(valuesMap)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fluxcd/pkg/apis/meta"
|
"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{
|
var createImagePolicyCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fluxcd/pkg/apis/meta"
|
"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{
|
var createImageRepositoryCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -22,9 +22,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fluxcd/pkg/apis/meta"
|
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||||
|
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var createImageUpdateCmd = &cobra.Command{
|
var createImageUpdateCmd = &cobra.Command{
|
||||||
@@ -113,25 +112,33 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
|
|||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
Spec: autov1.ImageUpdateAutomationSpec{
|
Spec: autov1.ImageUpdateAutomationSpec{
|
||||||
Checkout: autov1.GitCheckoutSpec{
|
SourceRef: autov1.SourceReference{
|
||||||
GitRepositoryRef: meta.LocalObjectReference{
|
Kind: sourcev1.GitRepositoryKind,
|
||||||
Name: imageUpdateArgs.gitRepoRef,
|
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{
|
Interval: metav1.Duration{
|
||||||
Duration: createArgs.interval,
|
Duration: createArgs.interval,
|
||||||
},
|
},
|
||||||
Commit: autov1.CommitSpec{
|
|
||||||
AuthorName: imageUpdateArgs.authorName,
|
|
||||||
AuthorEmail: imageUpdateArgs.authorEmail,
|
|
||||||
MessageTemplate: imageUpdateArgs.commitTemplate,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if imageUpdateArgs.pushBranch != "" {
|
if imageUpdateArgs.pushBranch != "" {
|
||||||
update.Spec.Push = &autov1.PushSpec{
|
update.Spec.GitSpec.Push = &autov1.PushSpec{
|
||||||
Branch: imageUpdateArgs.pushBranch,
|
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 \
|
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||||
--private-key-file=./private.key
|
--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
|
# Create a secret for a Git repository using basic authentication
|
||||||
flux create secret git podinfo-auth \
|
flux create secret git podinfo-auth \
|
||||||
--url=https://github.com/stefanprodan/podinfo \
|
--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.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(secretGitArgs.keyAlgorithm)
|
||||||
opts.RSAKeyBits = int(secretGitArgs.rsaBits)
|
opts.RSAKeyBits = int(secretGitArgs.rsaBits)
|
||||||
opts.ECDSACurve = secretGitArgs.ecdsaCurve.Curve
|
opts.ECDSACurve = secretGitArgs.ecdsaCurve.Curve
|
||||||
|
opts.Password = secretGitArgs.password
|
||||||
case "http", "https":
|
case "http", "https":
|
||||||
if secretGitArgs.username == "" || secretGitArgs.password == "" {
|
if secretGitArgs.username == "" || secretGitArgs.password == "" {
|
||||||
return fmt.Errorf("for Git over HTTP/S the username and password are required")
|
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 \
|
--branch=master \
|
||||||
--private-key-file=./private.key
|
--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
|
# Create a source for a Git repository using basic authentication
|
||||||
flux create source git podinfo \
|
flux create source git podinfo \
|
||||||
--url=https://github.com/stefanprodan/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.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(sourceGitArgs.keyAlgorithm)
|
||||||
secretOpts.RSAKeyBits = int(sourceGitArgs.keyRSABits)
|
secretOpts.RSAKeyBits = int(sourceGitArgs.keyRSABits)
|
||||||
secretOpts.ECDSACurve = sourceGitArgs.keyECDSACurve.Curve
|
secretOpts.ECDSACurve = sourceGitArgs.keyECDSACurve.Curve
|
||||||
|
secretOpts.Password = sourceGitArgs.password
|
||||||
case "https":
|
case "https":
|
||||||
secretOpts.Username = sourceGitArgs.username
|
secretOpts.Username = sourceGitArgs.username
|
||||||
secretOpts.Password = sourceGitArgs.password
|
secretOpts.Password = sourceGitArgs.password
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var deleteImagePolicyCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var deleteImageRepositoryCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var deleteImageUpdateCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
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{
|
var exportImagePolicyCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
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{
|
var exportImageRepositoryCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
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{
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var getImageAllCmd = &cobra.Command{
|
var getImageAllCmd = &cobra.Command{
|
||||||
@@ -33,6 +35,20 @@ var getImageAllCmd = &cobra.Command{
|
|||||||
# List all image objects in all namespaces
|
# List all image objects in all namespaces
|
||||||
flux get images all --all-namespaces`,
|
flux get images all --all-namespaces`,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
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{
|
c := getCommand{
|
||||||
apiType: imageRepositoryType,
|
apiType: imageRepositoryType,
|
||||||
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
|
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
|
||||||
@@ -41,20 +57,12 @@ var getImageAllCmd = &cobra.Command{
|
|||||||
logger.Failuref(err.Error())
|
logger.Failuref(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
c = getCommand{
|
for _, c := range allImageCmd {
|
||||||
apiType: imagePolicyType,
|
if err := c.run(cmd, args); err != nil {
|
||||||
list: &imagePolicyListAdapter{&imagev1.ImagePolicyList{}},
|
if !strings.Contains(err.Error(), "no matches for kind") {
|
||||||
}
|
logger.Failuref(err.Error())
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var getImagePolicyCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var getImageRepositoryCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var getImageUpdateCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||||
@@ -32,36 +34,31 @@ var getSourceAllCmd = &cobra.Command{
|
|||||||
# List all sources in all namespaces
|
# List all sources in all namespaces
|
||||||
flux get sources all --all-namespaces`,
|
flux get sources all --all-namespaces`,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
c := getCommand{
|
var allSourceCmd = []getCommand{
|
||||||
apiType: bucketType,
|
{
|
||||||
list: &bucketListAdapter{&sourcev1.BucketList{}},
|
apiType: bucketType,
|
||||||
}
|
list: &bucketListAdapter{&sourcev1.BucketList{}},
|
||||||
if err := c.run(cmd, args); err != nil {
|
},
|
||||||
logger.Failuref(err.Error())
|
{
|
||||||
|
apiType: gitRepositoryType,
|
||||||
|
list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiType: helmRepositoryType,
|
||||||
|
list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
apiType: helmChartType,
|
||||||
|
list: &helmChartListAdapter{&sourcev1.HelmChartList{}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
c = getCommand{
|
for _, c := range allSourceCmd {
|
||||||
apiType: gitRepositoryType,
|
if err := c.run(cmd, args); err != nil {
|
||||||
list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
|
if !strings.Contains(err.Error(), "no matches for kind") {
|
||||||
}
|
logger.Failuref(err.Error())
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1"
|
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
|
||||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// These are general-purpose adapters for attaching methods to, for
|
// These are general-purpose adapters for attaching methods to, for
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
||||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||||
@@ -60,7 +61,7 @@ func (obj helmReleaseAdapter) reconcileSource() bool {
|
|||||||
return rhrArgs.syncHrWithSource
|
return rhrArgs.syncHrWithSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj helmReleaseAdapter) getSource() (reconcileCommand, string) {
|
func (obj helmReleaseAdapter) getSource() (reconcileCommand, types.NamespacedName) {
|
||||||
var cmd reconcileCommand
|
var cmd reconcileCommand
|
||||||
switch obj.Spec.Chart.Spec.SourceRef.Kind {
|
switch obj.Spec.Chart.Spec.SourceRef.Kind {
|
||||||
case sourcev1.HelmRepositoryKind:
|
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"
|
"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{
|
var reconcileImageRepositoryCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
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"
|
meta "github.com/fluxcd/pkg/apis/meta"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
||||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||||
@@ -60,7 +61,7 @@ func (obj kustomizationAdapter) reconcileSource() bool {
|
|||||||
return rksArgs.syncKsWithSource
|
return rksArgs.syncKsWithSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj kustomizationAdapter) getSource() (reconcileCommand, string) {
|
func (obj kustomizationAdapter) getSource() (reconcileCommand, types.NamespacedName) {
|
||||||
var cmd reconcileCommand
|
var cmd reconcileCommand
|
||||||
switch obj.Spec.SourceRef.Kind {
|
switch obj.Spec.SourceRef.Kind {
|
||||||
case sourcev1.GitRepositoryKind:
|
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
|
adapter
|
||||||
reconcilable
|
reconcilable
|
||||||
reconcileSource() bool
|
reconcileSource() bool
|
||||||
getSource() (reconcileCommand, string)
|
getSource() (reconcileCommand, types.NamespacedName)
|
||||||
}
|
}
|
||||||
|
|
||||||
type reconcileWithSourceCommand struct {
|
type reconcileWithSourceCommand struct {
|
||||||
@@ -55,14 +55,13 @@ func (reconcile reconcileWithSourceCommand) run(cmd *cobra.Command, args []strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if reconcile.object.reconcileSource() {
|
if reconcile.object.reconcileSource() {
|
||||||
|
reconcileCmd, nsName := reconcile.object.getSource()
|
||||||
nsCopy := rootArgs.namespace
|
nsCopy := rootArgs.namespace
|
||||||
objectNs := reconcile.object.asClientObject().GetNamespace()
|
if nsName.Namespace != "" {
|
||||||
if objectNs != "" {
|
rootArgs.namespace = nsName.Namespace
|
||||||
rootArgs.namespace = reconcile.object.asClientObject().GetNamespace()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reconcileCmd, sourceName := reconcile.object.getSource()
|
err := reconcileCmd.run(nil, []string{nsName.Name})
|
||||||
err := reconcileCmd.run(nil, []string{sourceName})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var resumeImageRepositoryCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var resumeImageUpdateCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var suspendImageRepositoryCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var suspendImageUpdateCmd = &cobra.Command{
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ flux bootstrap git [flags]
|
|||||||
# Run bootstrap for a Git repository with a passwordless private key
|
# 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>
|
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
|
### Options
|
||||||
|
|||||||
@@ -54,8 +54,9 @@ flux bootstrap github [flags]
|
|||||||
--owner string GitHub user or organization name
|
--owner string GitHub user or organization name
|
||||||
--path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path
|
--path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path
|
||||||
--personal if true, the owner is assumed to be a GitHub user; otherwise an org
|
--personal if true, the owner is assumed to be a GitHub user; otherwise an org
|
||||||
--private if true, the repository is assumed to be private (default true)
|
--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
|
--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
|
--repository string GitHub repository name
|
||||||
--team stringArray GitHub team to be given maintainer access
|
--team stringArray GitHub team to be given maintainer access
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -51,8 +51,9 @@ flux bootstrap gitlab [flags]
|
|||||||
--owner string GitLab user or group name
|
--owner string GitLab user or group name
|
||||||
--path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path
|
--path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path
|
||||||
--personal if true, the owner is assumed to be a GitLab user; otherwise a group
|
--personal if true, the owner is assumed to be a GitLab user; otherwise a group
|
||||||
--private if true, the repository is assumed to be private (default true)
|
--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
|
--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
|
--repository string GitLab repository name
|
||||||
--team stringArray GitLab teams to be given maintainer access
|
--team stringArray GitLab teams to be given maintainer access
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ flux create helmrelease [name] [flags]
|
|||||||
```
|
```
|
||||||
--chart string Helm chart name or path
|
--chart string Helm chart name or path
|
||||||
--chart-version string Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)
|
--chart-version string Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)
|
||||||
|
--crds crds upgrade CRDs policy, available options are: (Skip, Create, CreateReplace)
|
||||||
--depends-on stringArray HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'
|
--depends-on stringArray HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'
|
||||||
-h, --help help for helmrelease
|
-h, --help help for helmrelease
|
||||||
--release-name string name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'
|
--release-name string name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ flux create secret git [name] [flags]
|
|||||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||||
--private-key-file=./private.key
|
--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
|
# Create a secret for a Git repository using basic authentication
|
||||||
flux create secret git podinfo-auth \
|
flux create secret git podinfo-auth \
|
||||||
--url=https://github.com/stefanprodan/podinfo \
|
--url=https://github.com/stefanprodan/podinfo \
|
||||||
|
|||||||
@@ -54,6 +54,15 @@ flux create source git [name] [flags]
|
|||||||
--branch=master \
|
--branch=master \
|
||||||
--private-key-file=./private.key
|
--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
|
# Create a source for a Git repository using basic authentication
|
||||||
flux create source git podinfo \
|
flux create source git podinfo \
|
||||||
--url=https://github.com/stefanprodan/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](../flux/) - Command line utility for assembling Kubernetes CD pipelines
|
||||||
* [flux get alert-providers](../flux_get_alert-providers/) - Get Provider statuses
|
* [flux get alert-providers](../flux_get_alert-providers/) - Get Provider statuses
|
||||||
* [flux get alerts](../flux_get_alerts/) - Get Alert 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 helmreleases](../flux_get_helmreleases/) - Get HelmRelease statuses
|
||||||
* [flux get images](../flux_get_images/) - Get image automation object status
|
* [flux get images](../flux_get_images/) - Get image automation object status
|
||||||
* [flux get kustomizations](../flux_get_kustomizations/) - Get Kustomization statuses
|
* [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
|
--export > ./$AUTO_PATH/my-app-auto.yaml
|
||||||
$ cat my-app-auto.yaml
|
$ cat my-app-auto.yaml
|
||||||
---
|
---
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImageUpdateAutomation
|
kind: ImageUpdateAutomation
|
||||||
metadata:
|
metadata:
|
||||||
name: my-app-auto
|
name: my-app-auto
|
||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
checkout:
|
|
||||||
branch: main
|
|
||||||
gitRepositoryRef:
|
|
||||||
name: flux-system
|
|
||||||
commit:
|
|
||||||
authorEmail: fluxbot@example.com
|
|
||||||
authorName: FluxBot
|
|
||||||
interval: 5m0s
|
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
|
#### Commit and check that the automation object works
|
||||||
@@ -357,14 +361,8 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
fluxcd.io/automated: "true"
|
fluxcd.io/automated: "true"
|
||||||
fluxcd.io/tag.app: semver:^5.0
|
fluxcd.io/tag.app: semver:^5.0
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: app
|
- name: app
|
||||||
@@ -395,14 +393,8 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
fluxcd.io/automated: "true"
|
fluxcd.io/automated: "true"
|
||||||
fluxcd.io/tag.app: semver:^5.0
|
fluxcd.io/tag.app: semver:^5.0
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: app
|
- name: app
|
||||||
@@ -420,7 +412,7 @@ $ flux create image repository podinfo-image \
|
|||||||
--export > ./$AUTO_PATH/podinfo-image.yaml
|
--export > ./$AUTO_PATH/podinfo-image.yaml
|
||||||
$ cat ./$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
|
kind: ImageRepository
|
||||||
metadata:
|
metadata:
|
||||||
name: podinfo-image
|
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:
|
`ImagePolicy` would look like this:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImagePolicy
|
kind: ImagePolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: my-app-policy
|
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:
|
Then you would use an `ImagePolicy` similar to this one:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImagePolicy
|
kind: ImagePolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: my-app-policy
|
name: my-app-policy
|
||||||
@@ -600,7 +592,7 @@ $ flux create image policy my-app-policy \
|
|||||||
--export > ./$AUTO_PATH/my-app-policy.yaml
|
--export > ./$AUTO_PATH/my-app-policy.yaml
|
||||||
$ cat ./$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
|
kind: ImagePolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: my-app-policy
|
name: my-app-policy
|
||||||
@@ -659,14 +651,8 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
fluxcd.io/automated: "true"
|
fluxcd.io/automated: "true"
|
||||||
fluxcd.io/tag.app: semver:^5.0 # <-- `.app` here
|
fluxcd.io/tag.app: semver:^5.0 # <-- `.app` here
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: app # <-- targets `app` here
|
- name: app # <-- targets `app` here
|
||||||
@@ -685,14 +671,8 @@ kind: Deployment
|
|||||||
metadata:
|
metadata:
|
||||||
namespace: default
|
namespace: default
|
||||||
name: my-app
|
name: my-app
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: podinfo
|
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: app
|
- name: app
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ Support for values references to `ConfigMap` and `Secret` resources in other nam
|
|||||||
|
|
||||||
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.
|
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.
|
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.
|
||||||
|
|
||||||
@@ -457,13 +457,15 @@ spec:
|
|||||||
version: 1.2.3
|
version: 1.2.3
|
||||||
# Alternative values file to use as the default values,
|
# Alternative values file to use as the default values,
|
||||||
# expected to be a relative path in the sourceRef
|
# expected to be a relative path in the sourceRef
|
||||||
valuesFile: values-prod.yaml
|
valuesFiles:
|
||||||
|
- values.yaml
|
||||||
|
- values-prod.yaml
|
||||||
sourceRef:
|
sourceRef:
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
name: my-repository
|
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
|
##### External source references
|
||||||
|
|
||||||
@@ -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.
|
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
|
### 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.
|
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
|
### 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)!
|
||||||
|
|||||||
@@ -378,12 +378,14 @@ spec:
|
|||||||
sourceRef:
|
sourceRef:
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
name: bitnami
|
name: bitnami
|
||||||
valuesFile: values-production.yaml
|
valuesFiles:
|
||||||
|
- values.yaml
|
||||||
|
- values-production.yaml
|
||||||
values:
|
values:
|
||||||
replicaCount: 5
|
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:
|
fetch the chart. To determine why the `HelmChart` fails to produce an artifact, you can inspect the status with:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ flux create image repository podinfo \
|
|||||||
The above command generates the following manifest:
|
The above command generates the following manifest:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImageRepository
|
kind: ImageRepository
|
||||||
metadata:
|
metadata:
|
||||||
name: podinfo
|
name: podinfo
|
||||||
@@ -177,7 +177,7 @@ flux create image policy podinfo \
|
|||||||
The above command generates the following manifest:
|
The above command generates the following manifest:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImagePolicy
|
kind: ImagePolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: podinfo
|
name: podinfo
|
||||||
@@ -258,23 +258,27 @@ flux create image update flux-system \
|
|||||||
The above command generates the following manifest:
|
The above command generates the following manifest:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImageUpdateAutomation
|
kind: ImageUpdateAutomation
|
||||||
metadata:
|
metadata:
|
||||||
name: flux-system
|
name: flux-system
|
||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
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
|
interval: 1m0s
|
||||||
push:
|
sourceRef:
|
||||||
branch: main
|
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:
|
update:
|
||||||
path: ./clusters/my-cluster
|
path: ./clusters/my-cluster
|
||||||
strategy: Setters
|
strategy: Setters
|
||||||
@@ -387,21 +391,20 @@ images:
|
|||||||
|
|
||||||
## Push updates to a different branch
|
## 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.
|
than the one used for checkout. If the specified branch doesn't exist, Flux will create it for you.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
|
||||||
kind: ImageUpdateAutomation
|
kind: ImageUpdateAutomation
|
||||||
metadata:
|
metadata:
|
||||||
name: flux-system
|
name: flux-system
|
||||||
spec:
|
spec:
|
||||||
checkout:
|
git:
|
||||||
branch: main
|
checkout:
|
||||||
gitRepositoryRef:
|
ref:
|
||||||
name: flux-system
|
branch: main
|
||||||
push:
|
push:
|
||||||
branch: image-updates
|
branch: flux-image-updates
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use CI automation e.g. GitHub Actions such as
|
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
|
## 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
|
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.:
|
lets you range over the objects and images e.g.:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
|
||||||
kind: ImageUpdateAutomation
|
kind: ImageUpdateAutomation
|
||||||
metadata:
|
metadata:
|
||||||
name: flux-system
|
name: flux-system
|
||||||
spec:
|
spec:
|
||||||
commit:
|
git:
|
||||||
messageTemplate: |
|
commit:
|
||||||
Automated image update
|
messageTemplate: |
|
||||||
|
Automated image update
|
||||||
|
|
||||||
Automation name: {{ .AutomationObject }}
|
Automation name: {{ .AutomationObject }}
|
||||||
|
|
||||||
Files:
|
Files:
|
||||||
{{ range $filename, $_ := .Updated.Files -}}
|
{{ range $filename, $_ := .Updated.Files -}}
|
||||||
- {{ $filename }}
|
- {{ $filename }}
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
|
|
||||||
Objects:
|
Objects:
|
||||||
{{ range $resource, $_ := .Updated.Objects -}}
|
{{ range $resource, $_ := .Updated.Objects -}}
|
||||||
- {{ $resource.Kind }} {{ $resource.Name }}
|
- {{ $resource.Kind }} {{ $resource.Name }}
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
|
|
||||||
Images:
|
Images:
|
||||||
{{ range .Updated.Images -}}
|
{{ range .Updated.Images -}}
|
||||||
- {{.}}
|
- {{.}}
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
authorEmail: flux@example.com
|
author:
|
||||||
authorName: flux
|
email: fluxcdbot@users.noreply.github.com
|
||||||
|
name: fluxcdbot
|
||||||
```
|
```
|
||||||
|
|
||||||
## Trigger image updates with webhooks
|
## 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
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
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:
|
patchesStrategicMerge:
|
||||||
- config-patches.yaml
|
- config-patches.yaml
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -337,16 +337,23 @@ please see [fluxcd/terraform-provider-flux](https://github.com/fluxcd/terraform-
|
|||||||
|
|
||||||
## Customize Flux manifests
|
## 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
|
```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`.
|
Assuming you want to add custom annotations and labels to the Flux controllers,
|
||||||
Create a Kustomize patch and set the metadata for source-controller and kustomize-controller pods:
|
edit `clusters/my-cluster/gotk-patches.yaml` and set the metadata for source-controller and kustomize-controller pods:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
@@ -376,26 +383,37 @@ spec:
|
|||||||
custom: label
|
custom: label
|
||||||
```
|
```
|
||||||
|
|
||||||
Save the above file as `flux-system-patch.yaml` inside the `clusters/production` dir.
|
Edit `clusters/my-cluster/kustomization.yaml` and set the resources and patches:
|
||||||
|
|
||||||
Edit `clusters/production/kustomization.yaml` and add the patch:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- flux-system
|
- gotk-components.yaml
|
||||||
|
- gotk-sync.yaml
|
||||||
patchesStrategicMerge:
|
patchesStrategicMerge:
|
||||||
- flux-system-patch.yaml
|
- gotk-patches.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
Push the changes to main branch:
|
Push the changes to main branch:
|
||||||
|
|
||||||
```sh
|
```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
|
## Dev install
|
||||||
|
|
||||||
|
|||||||
@@ -52,11 +52,12 @@ flux create helmrelease sealed-secrets \
|
|||||||
--target-namespace=flux-system \
|
--target-namespace=flux-system \
|
||||||
--source=HelmRepository/sealed-secrets \
|
--source=HelmRepository/sealed-secrets \
|
||||||
--chart=sealed-secrets \
|
--chart=sealed-secrets \
|
||||||
--chart-version="1.13.x"
|
--chart-version=">=1.15.0-0" \
|
||||||
|
--crds=CreateReplace
|
||||||
```
|
```
|
||||||
|
|
||||||
With chart version `1.13.x` we configure helm-controller to automatically upgrade the release
|
With chart version `>=1.15.0-0` we configure helm-controller to automatically upgrade the release
|
||||||
when a new chart patch version is fetched by source-controller.
|
when a new chart version is fetched by source-controller.
|
||||||
|
|
||||||
At startup, the sealed-secrets controller generates a 4096-bit RSA key pair and
|
At startup, the sealed-secrets controller generates a 4096-bit RSA key pair and
|
||||||
persists the private and public keys as Kubernetes secrets in the `flux-system` namespace.
|
persists the private and public keys as Kubernetes secrets in the `flux-system` namespace.
|
||||||
@@ -119,11 +120,11 @@ Helm repository manifest:
|
|||||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
metadata:
|
metadata:
|
||||||
name: stable
|
name: sealed-secrets
|
||||||
namespace: flux-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
interval: 1h0m0s
|
interval: 1h0m0s
|
||||||
url: https://charts.helm.sh/stable
|
url: https://bitnami-labs.github.io/sealed-secrets
|
||||||
```
|
```
|
||||||
|
|
||||||
Helm release manifest:
|
Helm release manifest:
|
||||||
@@ -140,11 +141,15 @@ spec:
|
|||||||
chart: sealed-secrets
|
chart: sealed-secrets
|
||||||
sourceRef:
|
sourceRef:
|
||||||
kind: HelmRepository
|
kind: HelmRepository
|
||||||
name: stable
|
name: sealed-secrets
|
||||||
version: "1.13.x"
|
version: ">=1.15.0-0"
|
||||||
interval: 1h0m0s
|
interval: 1h0m0s
|
||||||
releaseName: sealed-secrets
|
releaseName: sealed-secrets
|
||||||
targetNamespace: flux-system
|
targetNamespace: flux-system
|
||||||
|
install:
|
||||||
|
crds: Create
|
||||||
|
upgrade:
|
||||||
|
crds: CreateReplace
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! hint
|
!!! hint
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ $ date +%s
|
|||||||
Alternatively, you can use a serial number as part of the tag. Some CI platforms will provide a
|
Alternatively, you can use a serial number as part of the tag. Some CI platforms will provide a
|
||||||
build number in an environment variable, but that may not be reliable to use as a serial number --
|
build number in an environment variable, but that may not be reliable to use as a serial number --
|
||||||
check the platform documentation.
|
check the platform documentation.
|
||||||
|
For example, Github makes availabe the variable `github.run_number` which can be used as a reliable ever increasing serial number.
|
||||||
|
|
||||||
A commit count can be a reasonable stand-in for a serial number, if you build an image per commit
|
A commit count can be a reasonable stand-in for a serial number, if you build an image per commit
|
||||||
and you don't rewrite the branch in question:
|
and you don't rewrite the branch in question:
|
||||||
@@ -105,6 +106,39 @@ jobs:
|
|||||||
${{ env.IMAGE }}:${{ steps.prep.outputs.BUILD_ID }}
|
${{ env.IMAGE }}:${{ steps.prep.outputs.BUILD_ID }}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Alternative example utilizing github.run_number
|
||||||
|
|
||||||
|
Here is another example example of a [GitHub Actions job][gha-syntax] which tags images using Github action's built in `run_number`
|
||||||
|
and the git SHA1:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
build-push:
|
||||||
|
env:
|
||||||
|
IMAGE: org/my-app
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
# These are prerequisites for the docker build step
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and publish container image with tag
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
tags: |
|
||||||
|
${{ env.IMAGE }}:${{ github.sha }}-${{ github.run_number }}
|
||||||
|
```
|
||||||
|
|
||||||
## Using in an `ImagePolicy` object
|
## Using in an `ImagePolicy` object
|
||||||
|
|
||||||
When creating an `ImagePolicy` object, you will need to extract just the timestamp part of the tag,
|
When creating an `ImagePolicy` object, you will need to extract just the timestamp part of the tag,
|
||||||
@@ -112,10 +146,10 @@ using the `tagFilter` field. You can filter for a particular branch to restrict
|
|||||||
built from that branch.
|
built from that branch.
|
||||||
|
|
||||||
Here is an example that filters for only images built from `main` branch, and selects the most
|
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`):
|
recent according to a timestamp (created with `date +%s`) or according to the run number (`github.run_number` for example):
|
||||||
|
|
||||||
```
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImagePolicy
|
kind: ImagePolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: image-repo-policy
|
name: image-repo-policy
|
||||||
@@ -124,6 +158,7 @@ spec:
|
|||||||
imageRepositoryRef:
|
imageRepositoryRef:
|
||||||
name: image-repo
|
name: image-repo
|
||||||
filterTags:
|
filterTags:
|
||||||
|
## use "pattern: '(?P<ts>.*)-.+'" if you copied the workflow example using github.run_number
|
||||||
pattern: '^main-[a-f0-9]+-(?P<ts>[0-9]+)'
|
pattern: '^main-[a-f0-9]+-(?P<ts>[0-9]+)'
|
||||||
extract: '$ts'
|
extract: '$ts'
|
||||||
policy:
|
policy:
|
||||||
@@ -133,8 +168,8 @@ spec:
|
|||||||
|
|
||||||
If you don't care about the branch, that part can be a wildcard in the pattern:
|
If you don't care about the branch, that part can be a wildcard in the pattern:
|
||||||
|
|
||||||
```
|
```yaml
|
||||||
apiVersion: image.toolkit.fluxcd.io/v1alpha1
|
apiVersion: image.toolkit.fluxcd.io/v1alpha2
|
||||||
kind: ImagePolicy
|
kind: ImagePolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: image-repo-policy
|
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
|
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.
|
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
|
## 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/Masterminds/semver/v3 v3.1.0
|
||||||
github.com/cyphar/filepath-securejoin v0.2.2
|
github.com/cyphar/filepath-securejoin v0.2.2
|
||||||
github.com/fluxcd/go-git-providers v0.0.3
|
github.com/fluxcd/go-git-providers v0.0.3
|
||||||
github.com/fluxcd/helm-controller/api v0.9.0
|
github.com/fluxcd/helm-controller/api v0.10.0
|
||||||
github.com/fluxcd/image-automation-controller/api v0.8.0
|
github.com/fluxcd/image-automation-controller/api v0.9.0
|
||||||
github.com/fluxcd/image-reflector-controller/api v0.8.0
|
github.com/fluxcd/image-reflector-controller/api v0.9.0
|
||||||
github.com/fluxcd/kustomize-controller/api v0.11.0
|
github.com/fluxcd/kustomize-controller/api v0.11.1
|
||||||
github.com/fluxcd/notification-controller/api v0.12.0
|
github.com/fluxcd/notification-controller/api v0.13.0
|
||||||
github.com/fluxcd/pkg/apis/meta v0.8.0
|
github.com/fluxcd/pkg/apis/meta v0.9.0
|
||||||
github.com/fluxcd/pkg/runtime v0.10.1
|
github.com/fluxcd/pkg/runtime v0.11.0
|
||||||
github.com/fluxcd/pkg/ssh v0.0.5
|
github.com/fluxcd/pkg/ssh v0.0.5
|
||||||
github.com/fluxcd/pkg/untar v0.0.5
|
github.com/fluxcd/pkg/untar v0.0.5
|
||||||
github.com/fluxcd/pkg/version v0.0.1
|
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.1
|
||||||
github.com/go-git/go-git/v5 v5.1.0
|
github.com/go-git/go-git/v5 v5.1.0
|
||||||
github.com/google/go-containerregistry v0.2.0
|
github.com/google/go-containerregistry v0.2.0
|
||||||
github.com/manifoldco/promptui v0.7.0
|
github.com/manifoldco/promptui v0.7.0
|
||||||
@@ -25,11 +25,11 @@ require (
|
|||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/xanzy/go-gitlab v0.43.0 // indirect
|
github.com/xanzy/go-gitlab v0.43.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
|
||||||
k8s.io/api v0.20.2
|
k8s.io/api v0.20.4
|
||||||
k8s.io/apiextensions-apiserver v0.20.2
|
k8s.io/apiextensions-apiserver v0.20.4
|
||||||
k8s.io/apimachinery v0.20.2
|
k8s.io/apimachinery v0.20.4
|
||||||
k8s.io/cli-runtime v0.20.2 // indirect
|
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/cli-utils v0.22.2
|
||||||
sigs.k8s.io/controller-runtime v0.8.3
|
sigs.k8s.io/controller-runtime v0.8.3
|
||||||
sigs.k8s.io/kustomize/api v0.7.4
|
sigs.k8s.io/kustomize/api v0.7.4
|
||||||
|
|||||||
48
go.sum
48
go.sum
@@ -190,30 +190,31 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo
|
|||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
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 h1:pquQvTpd1a4V1efPyZWuVPeIKrTgV8QRoDY0VGH+qiw=
|
||||||
github.com/fluxcd/go-git-providers v0.0.3/go.mod h1:iaXf3nEq8MB/LzxfbNcCl48sAtIReUU7jqjJ7CEnfFQ=
|
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.10.0 h1:7z+DvzsTl31cZPAIqlydD6Z5BV9cpgJNQHwycqEri68=
|
||||||
github.com/fluxcd/helm-controller/api v0.9.0/go.mod h1:HIWSF3n1QU3hdqjQMFizFUZVr1uV+abmlGAEpB7vB9A=
|
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.8.0 h1:lcyoYEQNorNijObqY9ZdSEurt2nXCXgFmx+PcM9W+Dw=
|
github.com/fluxcd/image-automation-controller/api v0.9.0 h1:LzWN3LwOzX/Q3IOdI6oNLvob+Ne2LDe7POxfiLQg/bs=
|
||||||
github.com/fluxcd/image-automation-controller/api v0.8.0/go.mod h1:7E2dCvoxmTkDttp+Hk8v9eoSK/CdFmFhRKInEXC3yVY=
|
github.com/fluxcd/image-automation-controller/api v0.9.0/go.mod h1:gpz1FCM/zK4cqvGsyV4OJovFEFLm2lFI7IvJG2BeLgg=
|
||||||
github.com/fluxcd/image-reflector-controller/api v0.8.0 h1:6dTIcyJFApmcmT4HbitWBFvh6ne8jpp8QQseH9Q5hv0=
|
github.com/fluxcd/image-reflector-controller/api v0.9.0 h1:RJvzgsQfbHdbQGNjiSrunydAMzFxhc7Erw1vvniSARk=
|
||||||
github.com/fluxcd/image-reflector-controller/api v0.8.0/go.mod h1:J18L71jiHYrAu2dg0tgOkOjP+GtQldC1oslhTeX0jqc=
|
github.com/fluxcd/image-reflector-controller/api v0.9.0/go.mod h1:gFoTJFs977JhE1H6RQSlGwYJGw12aIFDi5ljAn3rtUc=
|
||||||
github.com/fluxcd/kustomize-controller/api v0.11.0 h1:pPeNh10vzlJQGmAMHLf2lJLVROJah2hu7JeUjjV4+74=
|
github.com/fluxcd/kustomize-controller/api v0.11.1 h1:seBEImagW+0+AVE4cXQGwJtNH7+26itWNL6VtvU2Sjk=
|
||||||
github.com/fluxcd/kustomize-controller/api v0.11.0/go.mod h1:uvt/PmSGP/n4SU5mRUa1r7HMwor7ofgBvJV5/rHNB54=
|
github.com/fluxcd/kustomize-controller/api v0.11.1/go.mod h1:dyRZGTc7ozlf00OhTkB19lbrKv/IjUB8FfBwcV2dO2w=
|
||||||
github.com/fluxcd/notification-controller/api v0.12.0 h1:yzRnDIdIqT9iV9W0fexJwAROu4ZSNBpKEs5dFf3KaPk=
|
github.com/fluxcd/notification-controller/api v0.13.0 h1:F7G6ktLUvWEi11VqqFtvkpt/dwF+GzSWx6CDTk6/mZU=
|
||||||
github.com/fluxcd/notification-controller/api v0.12.0/go.mod h1:CA02ixmq+kFN9eBkruvJClkMqffgRjYBMxym3AfhO6c=
|
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 h1:TkA80R0GopRY27VJqzKyS6ifiKIAfwBd7OHXtV3t2CI=
|
||||||
github.com/fluxcd/pkg/apis/kustomize v0.0.1/go.mod h1:JAFPfnRmcrAoG1gNiA8kmEXsnOBuDyZ/F5X4DAQcVV0=
|
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.9.0 h1:rxW69p+VmJCKXXkaRYnovRBFlKjd+MJQfm2RrB0B4j8=
|
||||||
github.com/fluxcd/pkg/apis/meta v0.8.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po=
|
github.com/fluxcd/pkg/apis/meta v0.9.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.11.0 h1:FPsiu1k5NQGl2tsaXH5WgSmrOMg7o44jdOP0rW/TI1Y=
|
||||||
github.com/fluxcd/pkg/runtime v0.10.1/go.mod h1:JD0eZIn5xkTeHHQUWXSqJPIh/ecO0d0qrUKbSVHnpnw=
|
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 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A=
|
||||||
github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs=
|
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 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk=
|
||||||
github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw=
|
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 h1:/8asQoDXSThz3csiwi4Qo8Zb6blAxLXbtxNgeMJ9bCg=
|
||||||
github.com/fluxcd/pkg/version v0.0.1/go.mod h1:WAF4FEEA9xyhngF8TDxg3UPu5fA1qhEYV8Pmi2Il01Q=
|
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.12.0/go.mod h1:+EPyhxC7Y+hUnq7EwAkkLtfbwCxJxF5yfmiyzDk43KY=
|
||||||
github.com/fluxcd/source-controller/api v0.11.0/go.mod h1:Vuw+7UqEUUOdkKBfTUPHwaQgbn6LL2FwqPDx2UAk7NE=
|
github.com/fluxcd/source-controller/api v0.12.1 h1:ubO3gwGaxnXwayJeDHpdsh96NXwOLpFcbLjZo/pqWCg=
|
||||||
|
github.com/fluxcd/source-controller/api v0.12.1/go.mod h1:+EPyhxC7Y+hUnq7EwAkkLtfbwCxJxF5yfmiyzDk43KY=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
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 h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
@@ -1133,25 +1134,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.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
|
||||||
k8s.io/api v0.18.10/go.mod h1:xWtwPX1v47j5RTncmlMFGCx8b0avh+nP8OgZZ9hjo3M=
|
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.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.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.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
|
||||||
k8s.io/apiextensions-apiserver v0.18.10/go.mod h1:XOE93YaGrb8Pa+ro00Jx3fhzRJ7UB0bU37jRTQXpTOM=
|
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.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.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.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
||||||
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
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.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
|
||||||
k8s.io/apimachinery v0.18.10/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
|
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.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.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.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
|
||||||
k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
|
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.18.10/go.mod h1:N4FaJo9BeSgmtvVByXi4fPSQPRqhvvLMGqswwkddob8=
|
||||||
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
|
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.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.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 h1:W0/FHdbApnl9oB7xdG643c/Zaf7TZT+43I+zKxwqvhU=
|
||||||
k8s.io/cli-runtime v0.20.2/go.mod h1:FjH6uIZZZP3XmwrXWeeYCbgxcrD6YXxoAykBaWH0VdM=
|
k8s.io/cli-runtime v0.20.2/go.mod h1:FjH6uIZZZP3XmwrXWeeYCbgxcrD6YXxoAykBaWH0VdM=
|
||||||
@@ -1160,19 +1165,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.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
|
||||||
k8s.io/client-go v0.18.10/go.mod h1:XBkFAqPrzqfwmGkV5ac+mlgBpWcz5TkhLw2808q8C3c=
|
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.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.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/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.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.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
||||||
k8s.io/code-generator v0.18.10/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
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.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.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.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
|
||||||
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
|
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.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.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
|
||||||
k8s.io/component-base v0.20.2/go.mod h1:pzFtCiwe/ASD0iV7ySMu8SYVJjCapNM9bjvk7ptpKh0=
|
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/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-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/gengo v0.0.0-20190822140433-26a664648505/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() {
|
setup_binary() {
|
||||||
chmod 755 "${TMP_BIN}"
|
chmod 755 "${TMP_BIN}"
|
||||||
info "Installing flux to ${BIN_DIR}/flux"
|
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}\""
|
local CMD_MOVE="mv -f \"${TMP_DIR}/flux\" \"${BIN_DIR}\""
|
||||||
if [[ -w "${BIN_DIR}" ]]; then
|
if [[ -w "${BIN_DIR}" ]]; then
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package bootstrap
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -29,6 +31,7 @@ import (
|
|||||||
"sigs.k8s.io/cli-utils/pkg/object"
|
"sigs.k8s.io/cli-utils/pkg/object"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
|
"sigs.k8s.io/kustomize/api/konfig"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||||
@@ -152,10 +155,48 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
|||||||
|
|
||||||
// Conditionally install manifests
|
// Conditionally install manifests
|
||||||
if mustInstallManifests(ctx, b.kube, options.Namespace) {
|
if mustInstallManifests(ctx, b.kube, options.Namespace) {
|
||||||
b.logger.Actionf("installing components in %q namespace", options.Namespace)
|
componentsYAML := filepath.Join(b.git.Path(), manifests.Path)
|
||||||
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 {
|
// Apply components using any existing customisations
|
||||||
return err
|
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")
|
b.logger.Successf("installed components")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ type GitProviderBootstrapper struct {
|
|||||||
defaultBranch string
|
defaultBranch string
|
||||||
visibility string
|
visibility string
|
||||||
|
|
||||||
|
reconcile bool
|
||||||
|
|
||||||
teams map[string]string
|
teams map[string]string
|
||||||
|
|
||||||
readWriteKey bool
|
readWriteKey bool
|
||||||
@@ -168,6 +170,16 @@ func (o sshHostnameOption) applyGitProvider(b *GitProviderBootstrapper) {
|
|||||||
b.sshHostname = string(o)
|
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 {
|
func (b *GitProviderBootstrapper) ReconcileSyncConfig(ctx context.Context, options sync.Options) error {
|
||||||
repo, err := b.getRepository(ctx)
|
repo, err := b.getRepository(ctx)
|
||||||
if err != nil {
|
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
|
// go-git-providers has at present some issues with the idempotency
|
||||||
// of the available Reconcile methods, and setting e.g. the default
|
// of the available Reconcile methods, and setting e.g. the default
|
||||||
// branch correctly. Resort to Create with AutoInit until this has
|
// branch correctly. Resort to Create until this has been resolved.
|
||||||
// been resolved.
|
repo, err = b.provider.OrgRepositories().Create(ctx, repoRef, repoInfo)
|
||||||
repo, err = b.provider.OrgRepositories().Create(ctx, repoRef, repoInfo, &gitprovider.RepositoryCreateOptions{
|
|
||||||
AutoInit: gitprovider.BoolVar(true),
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create new Git repository %q: %w", repoRef.String(), err)
|
return nil, fmt.Errorf("failed to create new Git repository %q: %w", repoRef.String(), err)
|
||||||
}
|
}
|
||||||
b.logger.Successf("repository %q created", repoRef.String())
|
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
|
var changed bool
|
||||||
if err = retry(1, 2*time.Second, func() (err error) {
|
if b.reconcile {
|
||||||
repo, changed, err = b.provider.OrgRepositories().Reconcile(ctx, repoRef, repoInfo)
|
// Set default branch before calling Reconcile due to bug described
|
||||||
return
|
// above.
|
||||||
}); err != nil {
|
repoInfo.DefaultBranch = repo.Get().DefaultBranch
|
||||||
return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err)
|
if err = retry(1, 2*time.Second, func() (err error) {
|
||||||
}
|
repo, changed, err = b.provider.OrgRepositories().Reconcile(ctx, repoRef, repoInfo)
|
||||||
if changed {
|
return
|
||||||
b.logger.Successf("repository %q reconciled", repoRef.String())
|
}); 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
|
// Build the team access config
|
||||||
@@ -310,9 +321,8 @@ func (b *GitProviderBootstrapper) reconcileOrgRepository(ctx context.Context) (g
|
|||||||
_, changed, err = repo.TeamAccess().Reconcile(ctx, i)
|
_, changed, err = repo.TeamAccess().Reconcile(ctx, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
warning = fmt.Errorf("failed to grant permissions to team: %w", ErrReconciledWithWarning)
|
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)
|
b.logger.Failuref("failed to grant %q permissions to %q: %s", *i.Permission, i.Name, err.Error())
|
||||||
}
|
} else if changed {
|
||||||
if changed {
|
|
||||||
b.logger.Successf("granted %q permissions to %q", *i.Permission, i.Name)
|
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)
|
repoRef := newUserRepositoryRef(userRef, repoName)
|
||||||
repoInfo := newRepositoryInfo(b.description, b.defaultBranch, b.visibility)
|
repoInfo := newRepositoryInfo(b.description, b.defaultBranch, b.visibility)
|
||||||
|
|
||||||
|
// Reconcile the user repository
|
||||||
repo, err := b.provider.UserRepositories().Get(ctx, repoRef)
|
repo, err := b.provider.UserRepositories().Get(ctx, repoRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, gitprovider.ErrNotFound) {
|
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
|
// go-git-providers has at present some issues with the idempotency
|
||||||
// of the available Reconcile methods, and setting e.g. the default
|
// of the available Reconcile methods, and setting e.g. the default
|
||||||
// branch correctly. Resort to Create with AutoInit until this has
|
// branch correctly. Resort to Create until this has been resolved.
|
||||||
// been resolved.
|
repo, err = b.provider.UserRepositories().Create(ctx, repoRef, repoInfo)
|
||||||
repo, err = b.provider.UserRepositories().Create(ctx, repoRef, repoInfo, &gitprovider.RepositoryCreateOptions{
|
|
||||||
AutoInit: gitprovider.BoolVar(true),
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create new Git repository %q: %w", repoRef.String(), err)
|
return nil, fmt.Errorf("failed to create new Git repository %q: %w", repoRef.String(), err)
|
||||||
}
|
}
|
||||||
b.logger.Successf("repository %q created", repoRef.String())
|
b.logger.Successf("repository %q created", repoRef.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set default branch before calling Reconcile due to bug described
|
if b.reconcile {
|
||||||
// above.
|
// Set default branch before calling Reconcile due to bug described
|
||||||
repoInfo.DefaultBranch = repo.Get().DefaultBranch
|
// above.
|
||||||
var changed bool
|
repoInfo.DefaultBranch = repo.Get().DefaultBranch
|
||||||
if err = retry(1, 2*time.Second, func() (err error) {
|
var changed bool
|
||||||
repo, changed, err = b.provider.UserRepositories().Reconcile(ctx, repoRef, repoInfo)
|
if err = retry(1, 2*time.Second, func() (err error) {
|
||||||
return
|
repo, changed, err = b.provider.UserRepositories().Reconcile(ctx, repoRef, repoInfo)
|
||||||
}); err != nil {
|
return
|
||||||
return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err)
|
}); 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 changed {
|
||||||
|
b.logger.Successf("repository %q reconciled", repoRef.String())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return repo, nil
|
return repo, nil
|
||||||
|
|||||||
60
internal/flags/crds.go
Normal file
60
internal/flags/crds.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
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 flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var supportedCRDsPolicies = []string{
|
||||||
|
string(helmv2.Skip),
|
||||||
|
string(helmv2.Create),
|
||||||
|
string(helmv2.CreateReplace),
|
||||||
|
}
|
||||||
|
|
||||||
|
type CRDsPolicy string
|
||||||
|
|
||||||
|
func (a *CRDsPolicy) String() string {
|
||||||
|
return string(*a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *CRDsPolicy) Set(str string) error {
|
||||||
|
if strings.TrimSpace(str) == "" {
|
||||||
|
return fmt.Errorf("no upgrade CRDs policy given, must be one of: %s",
|
||||||
|
strings.Join(supportedCRDsPolicies, ", "))
|
||||||
|
}
|
||||||
|
if !utils.ContainsItemString(supportedCRDsPolicies, str) {
|
||||||
|
return fmt.Errorf("unsupported upgrade CRDs policy '%s', must be one of: %s",
|
||||||
|
str, strings.Join(supportedCRDsPolicies, ", "))
|
||||||
|
|
||||||
|
}
|
||||||
|
*a = CRDsPolicy(str)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *CRDsPolicy) Type() string {
|
||||||
|
return "crds"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *CRDsPolicy) Description() string {
|
||||||
|
return fmt.Sprintf("upgrade CRDs policy, available options are: (%s)", strings.Join(supportedCRDsPolicies, ", "))
|
||||||
|
}
|
||||||
45
internal/flags/crds_test.go
Normal file
45
internal/flags/crds_test.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
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 flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCRDsPolicy_Set(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
str string
|
||||||
|
expect string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{"supported", "CreateReplace", "CreateReplace", false},
|
||||||
|
{"unsupported", "createreplace", "", true},
|
||||||
|
{"empty", "", "", true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var a CRDsPolicy
|
||||||
|
if err := a.Set(tt.str); (err != nil) != tt.expectErr {
|
||||||
|
t.Errorf("Set() error = %v, expectErr %v", err, tt.expectErr)
|
||||||
|
}
|
||||||
|
if str := a.String(); str != tt.expect {
|
||||||
|
t.Errorf("Set() = %v, expect %v", str, tt.expect)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -29,24 +30,28 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"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"
|
"github.com/olekukonko/tablewriter"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
sigyaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"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"
|
"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()
|
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
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
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.10.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.deployment.yaml
|
||||||
- account.yaml
|
- account.yaml
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
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.9.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.deployment.yaml
|
||||||
- account.yaml
|
- account.yaml
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
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.9.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.deployment.yaml
|
||||||
- account.yaml
|
- account.yaml
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
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.1/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.deployment.yaml
|
||||||
- account.yaml
|
- account.yaml
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
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.13.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.deployment.yaml
|
||||||
- account.yaml
|
- account.yaml
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
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.12.1/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.1/source-controller.deployment.yaml
|
||||||
- account.yaml
|
- account.yaml
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
|
|||||||
9
manifests/crds/kustomization.yaml
Normal file
9
manifests/crds/kustomization.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- https://github.com/fluxcd/source-controller/releases/download/v0.12.1/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
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: NetworkPolicy
|
kind: NetworkPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: deny-ingress
|
name: allow-egress
|
||||||
spec:
|
spec:
|
||||||
policyTypes:
|
policyTypes:
|
||||||
- Ingress
|
- Ingress
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- deny-ingress.yaml
|
- allow-egress.yaml
|
||||||
- allow-scraping.yaml
|
- allow-scraping.yaml
|
||||||
- allow-webhooks.yaml
|
- allow-webhooks.yaml
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ nav:
|
|||||||
- Sortable image tags to use with automation: guides/sortable-image-tags.md
|
- Sortable image tags to use with automation: guides/sortable-image-tags.md
|
||||||
- Use Cases:
|
- Use Cases:
|
||||||
- Azure: use-cases/azure.md
|
- Azure: use-cases/azure.md
|
||||||
|
- GitHub Actions Manifest Generation: use-cases/gh-actions-manifest-generation.md
|
||||||
|
- Helm: use-cases/helm.md
|
||||||
- Toolkit Components:
|
- Toolkit Components:
|
||||||
- Overview: components/index.md
|
- Overview: components/index.md
|
||||||
- Source Controller:
|
- Source Controller:
|
||||||
@@ -147,6 +149,7 @@ nav:
|
|||||||
- Export image repository: cmd/flux_export_image_repository.md
|
- Export image repository: cmd/flux_export_image_repository.md
|
||||||
- Export image update: cmd/flux_export_image_update.md
|
- Export image update: cmd/flux_export_image_update.md
|
||||||
- Get: cmd/flux_get.md
|
- Get: cmd/flux_get.md
|
||||||
|
- Get all: cmd/flux_get_all.md
|
||||||
- Get kustomizations: cmd/flux_get_kustomizations.md
|
- Get kustomizations: cmd/flux_get_kustomizations.md
|
||||||
- Get helmreleases: cmd/flux_get_helmreleases.md
|
- Get helmreleases: cmd/flux_get_helmreleases.md
|
||||||
- Get sources: cmd/flux_get_sources.md
|
- Get sources: cmd/flux_get_sources.md
|
||||||
|
|||||||
@@ -41,10 +41,10 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
|||||||
|
|
||||||
var keypair *ssh.KeyPair
|
var keypair *ssh.KeyPair
|
||||||
switch {
|
switch {
|
||||||
case options.Username != "", options.Password != "":
|
case options.Username != "" && options.Password != "":
|
||||||
// noop
|
// noop
|
||||||
case len(options.PrivateKeyPath) > 0:
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
case len(options.PrivateKeyAlgorithm) > 0:
|
case len(options.PrivateKeyAlgorithm) > 0:
|
||||||
@@ -101,7 +101,7 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile []byte
|
|||||||
secret.Labels = options.Labels
|
secret.Labels = options.Labels
|
||||||
secret.StringData = map[string]string{}
|
secret.StringData = map[string]string{}
|
||||||
|
|
||||||
if options.Username != "" || options.Password != "" {
|
if options.Username != "" && options.Password != "" {
|
||||||
secret.StringData[UsernameSecretKey] = options.Username
|
secret.StringData[UsernameSecretKey] = options.Username
|
||||||
secret.StringData[PasswordSecretKey] = options.Password
|
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[PrivateKeySecretKey] = string(keypair.PrivateKey)
|
||||||
secret.StringData[PublicKeySecretKey] = string(keypair.PublicKey)
|
secret.StringData[PublicKeySecretKey] = string(keypair.PublicKey)
|
||||||
secret.StringData[KnownHostsSecretKey] = string(hostKey)
|
secret.StringData[KnownHostsSecretKey] = string(hostKey)
|
||||||
|
// set password if present
|
||||||
|
if options.Password != "" {
|
||||||
|
secret.StringData[PasswordSecretKey] = string(options.Password)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadKeyPair(path string) (*ssh.KeyPair, error) {
|
func loadKeyPair(path string, password string) (*ssh.KeyPair, error) {
|
||||||
b, err := ioutil.ReadFile(path)
|
b, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open private key file: %w", err)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,23 +18,82 @@ package sourcesecret
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
"golang.org/x/crypto/ssh/testdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_loadKeyPair(t *testing.T) {
|
func Test_passwordLoadKeyPair(t *testing.T) {
|
||||||
pk, _ := ioutil.ReadFile("testdata/rsa")
|
tests := []struct {
|
||||||
ppk, _ := ioutil.ReadFile("testdata/rsa.pub")
|
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")
|
for _, tt := range tests {
|
||||||
if err != nil {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Errorf("loadKeyPair() error = %v", err)
|
pk, _ := ioutil.ReadFile(tt.privateKeyPath)
|
||||||
return
|
ppk, _ := ioutil.ReadFile(tt.publicKeyPath)
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got.PrivateKey, pk) {
|
got, err := loadKeyPair(tt.privateKeyPath, tt.password)
|
||||||
t.Errorf("PrivateKey %s != %s", got.PrivateKey, pk)
|
if err != nil {
|
||||||
}
|
t.Errorf("loadKeyPair() error = %v", err)
|
||||||
if !reflect.DeepEqual(got.PublicKey, ppk) {
|
return
|
||||||
t.Errorf("PublicKey %s != %s", got.PublicKey, ppk)
|
}
|
||||||
|
|
||||||
|
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