Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c61cfcbd18 | ||
|
|
eba2dd36e0 | ||
|
|
2a75754561 | ||
|
|
d03944893d | ||
|
|
884c6ebd37 | ||
|
|
331ac3f031 | ||
|
|
ccc84a8367 | ||
|
|
daeb41c31b | ||
|
|
17bda9c110 | ||
|
|
febedaad8f | ||
|
|
d1357dff1f | ||
|
|
102552427f | ||
|
|
f33898265d | ||
|
|
57bdaf939a | ||
|
|
981fed111b | ||
|
|
3a4a2002d4 | ||
|
|
b8d4af5538 | ||
|
|
0646538cef | ||
|
|
70a87247e2 | ||
|
|
61129c6b6a | ||
|
|
c158f95130 | ||
|
|
ad90d37f14 | ||
|
|
73ba754481 | ||
|
|
7dcfbdbb29 | ||
|
|
f453507fcc | ||
|
|
c5465de000 | ||
|
|
352b864636 | ||
|
|
c034befbb5 | ||
|
|
572cdf40fc | ||
|
|
0c0d353e9c | ||
|
|
bcc90afba2 | ||
|
|
a919703011 | ||
|
|
3300a45c39 | ||
|
|
f1cfae8f26 | ||
|
|
62763961be | ||
|
|
f1dab2279d | ||
|
|
ea337cf839 | ||
|
|
27277136f8 | ||
|
|
dd0b807fe4 | ||
|
|
ed09dd57b6 | ||
|
|
58b4c980c1 | ||
|
|
dd5165dcbf | ||
|
|
6da22613fe | ||
|
|
d0926776a5 | ||
|
|
14dc39e8d2 | ||
|
|
f0f2a79384 | ||
|
|
7b6f875920 | ||
|
|
52cec044b8 | ||
|
|
07dd59892f | ||
|
|
ffeaa683c5 | ||
|
|
1301bf7c15 | ||
|
|
69387fd2a4 | ||
|
|
12a0ebe3ba | ||
|
|
3de81827eb | ||
|
|
a7362b60e7 | ||
|
|
5d4bb3a43f | ||
|
|
d02d507812 | ||
|
|
554de7ba6f | ||
|
|
5d9ccc973d | ||
|
|
53ffb8aa00 | ||
|
|
c4da4a81aa | ||
|
|
b824ea8858 | ||
|
|
22e26efec1 |
3
.github/workflows/bootstrap.yaml
vendored
3
.github/workflows/bootstrap.yaml
vendored
@@ -49,8 +49,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
|
||||||
- name: uninstall
|
- name: uninstall
|
||||||
run: |
|
run: |
|
||||||
./bin/flux suspend kustomization flux-system
|
./bin/flux uninstall --resources --crds -s --timeout=10m
|
||||||
./bin/flux uninstall --resources --crds -s
|
|
||||||
- name: bootstrap reinstall
|
- name: bootstrap reinstall
|
||||||
run: |
|
run: |
|
||||||
./bin/flux bootstrap github --manifests ./manifests/install/ \
|
./bin/flux bootstrap github --manifests ./manifests/install/ \
|
||||||
|
|||||||
11
.github/workflows/e2e.yaml
vendored
11
.github/workflows/e2e.yaml
vendored
@@ -146,12 +146,21 @@ jobs:
|
|||||||
--chart=podinfo \
|
--chart=podinfo \
|
||||||
--chart-version="5.0.x" \
|
--chart-version="5.0.x" \
|
||||||
--service-account=dev-team
|
--service-account=dev-team
|
||||||
|
- name: flux2-kustomize-helm-example
|
||||||
|
run: |
|
||||||
|
./bin/flux create source git flux-system \
|
||||||
|
--url=https://github.com/fluxcd/flux2-kustomize-helm-example \
|
||||||
|
--branch=main
|
||||||
|
./bin/flux create kustomization flux-system \
|
||||||
|
--source=flux-system \
|
||||||
|
--path=./clusters/staging
|
||||||
|
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=2m
|
||||||
- name: flux check
|
- name: flux check
|
||||||
run: |
|
run: |
|
||||||
./bin/flux check
|
./bin/flux check
|
||||||
- name: flux uninstall
|
- name: flux uninstall
|
||||||
run: |
|
run: |
|
||||||
./bin/flux uninstall --crds --silent
|
./bin/flux uninstall --crds --silent --timeout=10m
|
||||||
- name: Debug failure
|
- name: Debug failure
|
||||||
if: failure()
|
if: failure()
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Flux is [Apache 2.0
|
Flux is [Apache 2.0 licensed](https://github.com/fluxcd/flux2/blob/main/LICENSE) and
|
||||||
licensed](https://github.com/fluxcd/flux2/blob/main/LICENSE) and
|
|
||||||
accepts contributions via GitHub pull requests. This document outlines
|
accepts contributions via GitHub pull requests. This document outlines
|
||||||
some of the conventions on to make it easier to get your contribution
|
some of the conventions on to make it easier to get your contribution
|
||||||
accepted.
|
accepted.
|
||||||
@@ -14,9 +13,18 @@ code.
|
|||||||
By contributing to this project you agree to the Developer Certificate of
|
By contributing to this project you agree to the Developer Certificate of
|
||||||
Origin (DCO). This document was created by the Linux Kernel community and is a
|
Origin (DCO). This document was created by the Linux Kernel community and is a
|
||||||
simple statement that you, as a contributor, have the legal right to make the
|
simple statement that you, as a contributor, have the legal right to make the
|
||||||
contribution. No action from you is required, but it's a good idea to see the
|
contribution.
|
||||||
[DCO](DCO) file for details before you start contributing code to FluxCD
|
|
||||||
organization.
|
We require all commits to be signed. By signing off with your signature, you
|
||||||
|
certify that you wrote the patch or otherwise have the right to contribute the
|
||||||
|
material by the rules of the [DCO](DCO):
|
||||||
|
|
||||||
|
`Signed-off-by: Jane Doe <jane.doe@example.com>`
|
||||||
|
|
||||||
|
The signature must contain your real name
|
||||||
|
(sorry, no pseudonyms or anonymous contributions)
|
||||||
|
If your `user.name` and `user.email` are configured in your Git config,
|
||||||
|
you can sign your commit automatically with `git commit -s`.
|
||||||
|
|
||||||
## Communications
|
## Communications
|
||||||
|
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -108,17 +108,17 @@ Depending on what you want to do, some of the following bits might be your first
|
|||||||
- Check out [how to contribute](CONTRIBUTING.md) to the project
|
- Check out [how to contribute](CONTRIBUTING.md) to the project
|
||||||
|
|
||||||
### Upcoming Events
|
### Upcoming Events
|
||||||
|
- 11 Jan 2021 - [Helm + GitOps = ⚡️⚡️⚡️ with Scott Rigby](https://www.meetup.com/GitOps-Community/events/275348736/)
|
||||||
- 14 Dec 2020 - [The Power of GitOps with Flux and Flagger with Leigh Capili](https://www.meetup.com/GitOps-Community/events/274924513/)
|
|
||||||
|
|
||||||
### Featured Talks
|
### Featured Talks
|
||||||
|
- 14 Dec 2020 - [The Power of GitOps with Flux and Flagger (GitOps Hands-On) with Leigh Capili](https://youtu.be/cB7iXeNLteE)
|
||||||
|
- 30 Nov 2020 - [The Power of GitOps with Flux 2 - Part 3 with Leigh Capili](https://youtu.be/N_K5g7o9JKg)
|
||||||
- 24 Nov 2020 - [Flux CD v2 with GitOps Toolkit - Kubernetes Deployment and Sync Mechanism](https://youtu.be/R6OeIgb7lUI)
|
- 24 Nov 2020 - [Flux CD v2 with GitOps Toolkit - Kubernetes Deployment and Sync Mechanism](https://youtu.be/R6OeIgb7lUI)
|
||||||
|
- 02 Nov 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 2 with Leigh Capili](https://youtu.be/fC2YCxQRUwU)
|
||||||
- 28 Oct 2020 - [The Kubelist Podcast: Flux with Michael Bridgen](https://www.heavybit.com/library/podcasts/the-kubelist-podcast/ep-5-flux-with-michael-bridgen-of-weaveworks/)
|
- 28 Oct 2020 - [The Kubelist Podcast: Flux with Michael Bridgen](https://www.heavybit.com/library/podcasts/the-kubelist-podcast/ep-5-flux-with-michael-bridgen-of-weaveworks/)
|
||||||
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 1 with Leigh Capili](https://youtu.be/0v5bjysXTL8)
|
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 1 with Leigh Capili](https://youtu.be/0v5bjysXTL8)
|
||||||
- 30 Nov 2020 - [The Power of GitOps with Flux 2 - Part 3 with Leigh Capili](https://youtu.be/N_K5g7o9JKg)
|
|
||||||
- 12 Oct 2020 - [Rawkode Live: Introduction to GitOps Toolkit with Stefan Prodan](https://youtu.be/HqTzuOBP0eY)
|
- 12 Oct 2020 - [Rawkode Live: Introduction to GitOps Toolkit with Stefan Prodan](https://youtu.be/HqTzuOBP0eY)
|
||||||
- 4 Sep 2020 - [KubeCon Europe: The road to Flux v2 and Progressive Delivery with Stefan Prodan & Hidde Beydals](https://youtu.be/8v94nUkXsxU)
|
- 04 Sep 2020 - [KubeCon Europe: The road to Flux v2 and Progressive Delivery with Stefan Prodan & Hidde Beydals](https://youtu.be/8v94nUkXsxU)
|
||||||
- 25 June 2020 - [Cloud Native Nordics: Introduction to GitOps & GitOps Toolkit with Alexis Richardson & Stefan Prodan](https://youtu.be/qQBtSkgl7tI)
|
- 25 Jun 2020 - [Cloud Native Nordics: Introduction to GitOps & GitOps Toolkit with Alexis Richardson & Stefan Prodan](https://youtu.be/qQBtSkgl7tI)
|
||||||
|
|
||||||
We are looking forward to seeing you with us!
|
We look forward to seeing you with us!
|
||||||
|
|||||||
@@ -10,6 +10,16 @@ Usage:
|
|||||||
run: flux -v
|
run: flux -v
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This action places the `flux` binary inside your repository root under `bin/flux`.
|
||||||
|
You should add `bin/flux` to your `.gitignore` file, as in the following example:
|
||||||
|
|
||||||
|
```gitignore
|
||||||
|
# ignore flux binary
|
||||||
|
bin/flux
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that this action can only be used on GitHub **Linux AMD64** runners.
|
||||||
|
|
||||||
### Automate Flux updates
|
### Automate Flux updates
|
||||||
|
|
||||||
Example workflow for updating Flux's components generated with `flux bootstrap --arch=amd64 --path=clusters/production`:
|
Example workflow for updating Flux's components generated with `flux bootstrap --arch=amd64 --path=clusters/production`:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ curl -sL $BIN_URL | tar xz
|
|||||||
|
|
||||||
# Copy binary to GitHub runner
|
# Copy binary to GitHub runner
|
||||||
mkdir -p $GITHUB_WORKSPACE/bin
|
mkdir -p $GITHUB_WORKSPACE/bin
|
||||||
cp ./flux $GITHUB_WORKSPACE/bin
|
mv ./flux $GITHUB_WORKSPACE/bin
|
||||||
chmod +x $GITHUB_WORKSPACE/bin/flux
|
chmod +x $GITHUB_WORKSPACE/bin/flux
|
||||||
|
|
||||||
# Print version
|
# Print version
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ func bootstrapValidate() error {
|
|||||||
return fmt.Errorf("component %s is required", component)
|
return fmt.Errorf("component %s is required", component)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := utils.ValidateComponents(components); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +239,7 @@ func shouldCreateDeployKey(ctx context.Context, kubeClient client.Client, namesp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateDeployKey(ctx context.Context, kubeClient client.Client, url *url.URL, namespace string) (string, error) {
|
func generateDeployKey(ctx context.Context, kubeClient client.Client, url *url.URL, namespace string) (string, error) {
|
||||||
pair, err := generateKeyPair(ctx)
|
pair, err := generateKeyPair(ctx, sourceGitKeyAlgorithm, sourceGitRSABits, sourceGitECDSACurve)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -261,3 +266,20 @@ func generateDeployKey(ctx context.Context, kubeClient client.Client, url *url.U
|
|||||||
|
|
||||||
return string(pair.PublicKey), nil
|
return string(pair.PublicKey), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkIfBootstrapPathDiffers(ctx context.Context, kubeClient client.Client, namespace string, path string) (string, bool) {
|
||||||
|
namespacedName := types.NamespacedName{
|
||||||
|
Name: namespace,
|
||||||
|
Namespace: namespace,
|
||||||
|
}
|
||||||
|
var fluxSystemKustomization kustomizev1.Kustomization
|
||||||
|
err := kubeClient.Get(ctx, namespacedName, &fluxSystemKustomization)
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if fluxSystemKustomization.Spec.Path == path {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
return fluxSystemKustomization.Spec.Path, true
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -114,6 +115,20 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(ctx, kubeClient, namespace, filepath.ToSlash(ghPath.String()))
|
||||||
|
|
||||||
|
if bootstrapPathDiffers {
|
||||||
|
return fmt.Errorf("cluster already bootstrapped to %v path", usedPath)
|
||||||
|
}
|
||||||
|
|
||||||
repository, err := git.NewRepository(ghRepository, ghOwner, ghHostname, ghToken, "flux", ghOwner+"@users.noreply.github.com")
|
repository, err := git.NewRepository(ghRepository, ghOwner, ghHostname, ghToken, "flux", ghOwner+"@users.noreply.github.com")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -134,9 +149,6 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
if ghDelete {
|
if ghDelete {
|
||||||
if err := provider.DeleteRepository(ctx, repository); err != nil {
|
if err := provider.DeleteRepository(ctx, repository); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -197,11 +209,6 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
logger.Successf("components are up to date")
|
logger.Successf("components are up to date")
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine if repo synchronization is working
|
// determine if repo synchronization is working
|
||||||
isInstall := shouldInstallManifests(ctx, kubeClient, namespace)
|
isInstall := shouldInstallManifests(ctx, kubeClient, namespace)
|
||||||
|
|
||||||
@@ -261,7 +268,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
// configure repo synchronization
|
// configure repo synchronization
|
||||||
logger.Actionf("generating sync manifests")
|
logger.Actionf("generating sync manifests")
|
||||||
syncManifests, err := generateSyncManifests(repoURL, bootstrapBranch, namespace, namespace, ghPath.String(), tmpDir, ghInterval)
|
syncManifests, err := generateSyncManifests(repoURL, bootstrapBranch, namespace, namespace, filepath.ToSlash(ghPath.String()), tmpDir, ghInterval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -67,6 +69,10 @@ the bootstrap command will perform an upgrade if needed.`,
|
|||||||
RunE: bootstrapGitLabCmdRun,
|
RunE: bootstrapGitLabCmdRun,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
gitlabProjectRegex = `\A[[:alnum:]\x{00A9}-\x{1f9ff}_][[:alnum:]\p{Pd}\x{00A9}-\x{1f9ff}_\.]*\z`
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
glOwner string
|
glOwner string
|
||||||
glRepository string
|
glRepository string
|
||||||
@@ -97,10 +103,32 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("%s environment variable not found", git.GitLabTokenName)
|
return fmt.Errorf("%s environment variable not found", git.GitLabTokenName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
projectNameIsValid, err := regexp.MatchString(gitlabProjectRegex, glRepository)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !projectNameIsValid {
|
||||||
|
return fmt.Errorf("%s is an invalid project name for gitlab.\nIt can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'.", glRepository)
|
||||||
|
}
|
||||||
|
|
||||||
if err := bootstrapValidate(); err != nil {
|
if err := bootstrapValidate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(ctx, kubeClient, namespace, filepath.ToSlash(glPath.String()))
|
||||||
|
|
||||||
|
if bootstrapPathDiffers {
|
||||||
|
return fmt.Errorf("cluster already bootstrapped to %v path", usedPath)
|
||||||
|
}
|
||||||
|
|
||||||
repository, err := git.NewRepository(glRepository, glOwner, glHostname, glToken, "flux", glOwner+"@users.noreply.gitlab.com")
|
repository, err := git.NewRepository(glRepository, glOwner, glHostname, glToken, "flux", glOwner+"@users.noreply.gitlab.com")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -115,20 +143,12 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
IsPersonal: glPersonal,
|
IsPersonal: glPersonal,
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDir, err := ioutil.TempDir("", namespace)
|
tmpDir, err := ioutil.TempDir("", namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// create GitLab project if doesn't exists
|
// create GitLab project if doesn't exists
|
||||||
logger.Actionf("connecting to %s", glHostname)
|
logger.Actionf("connecting to %s", glHostname)
|
||||||
changed, err := provider.CreateRepository(ctx, repository)
|
changed, err := provider.CreateRepository(ctx, repository)
|
||||||
@@ -227,7 +247,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
// configure repo synchronization
|
// configure repo synchronization
|
||||||
logger.Actionf("generating sync manifests")
|
logger.Actionf("generating sync manifests")
|
||||||
syncManifests, err := generateSyncManifests(repoURL, bootstrapBranch, namespace, namespace, glPath.String(), tmpDir, glInterval)
|
syncManifests, err := generateSyncManifests(repoURL, bootstrapBranch, namespace, namespace, filepath.ToSlash(glPath.String()), tmpDir, glInterval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var checkCmd = &cobra.Command{
|
var checkCmd = &cobra.Command{
|
||||||
@@ -133,7 +132,7 @@ func kubectlCheck(ctx context.Context, version string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func kubernetesCheck(version string) bool {
|
func kubernetesCheck(version string) bool {
|
||||||
cfg, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
|
cfg, err := utils.KubeConfig(kubeconfig, kubecontext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
|
logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ command -v flux >/dev/null && . <(flux completion zsh) && compdef _flux flux
|
|||||||
or write a cached file in one of the completion directories in your ${fpath}:
|
or write a cached file in one of the completion directories in your ${fpath}:
|
||||||
|
|
||||||
echo "${fpath// /\n}" | grep -i completion
|
echo "${fpath// /\n}" | grep -i completion
|
||||||
flux completions zsh > _flux
|
flux completion zsh > _flux
|
||||||
|
|
||||||
mv _flux ~/.oh-my-zsh/completions # oh-my-zsh
|
mv _flux ~/.oh-my-zsh/completions # oh-my-zsh
|
||||||
mv _flux ~/.zprezto/modules/completion/external/src/ # zprezto
|
mv _flux ~/.zprezto/modules/completion/external/src/ # zprezto
|
||||||
|
|||||||
@@ -17,11 +17,15 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,6 +39,32 @@ func init() {
|
|||||||
createCmd.AddCommand(createSecretCmd)
|
createCmd.AddCommand(createSecretCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func upsertSecret(ctx context.Context, kubeClient client.Client, secret corev1.Secret) error {
|
||||||
|
namespacedName := types.NamespacedName{
|
||||||
|
Namespace: secret.GetNamespace(),
|
||||||
|
Name: secret.GetName(),
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing corev1.Secret
|
||||||
|
err := kubeClient.Get(ctx, namespacedName, &existing)
|
||||||
|
if err != nil {
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
if err := kubeClient.Create(ctx, &secret); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
existing.StringData = secret.StringData
|
||||||
|
if err := kubeClient.Update(ctx, &existing); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func exportSecret(secret corev1.Secret) error {
|
func exportSecret(secret corev1.Secret) error {
|
||||||
secret.TypeMeta = metav1.TypeMeta{
|
secret.TypeMeta = metav1.TypeMeta{
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@@ -28,6 +29,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fluxcd/flux2/internal/flags"
|
"github.com/fluxcd/flux2/internal/flags"
|
||||||
"github.com/fluxcd/flux2/internal/utils"
|
"github.com/fluxcd/flux2/internal/utils"
|
||||||
|
"github.com/fluxcd/pkg/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
var createSecretGitCmd = &cobra.Command{
|
var createSecretGitCmd = &cobra.Command{
|
||||||
@@ -53,7 +55,7 @@ For Git over HTTP/S, the provided basic authentication credentials are stored in
|
|||||||
# Create a Git SSH secret on disk and print the deploy key
|
# Create a Git SSH secret on disk and print the deploy key
|
||||||
flux create secret git podinfo-auth \
|
flux create secret git podinfo-auth \
|
||||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||||
--export > podinfo-auth.yaml
|
--export > podinfo-auth.yaml
|
||||||
|
|
||||||
yq read podinfo-auth.yaml 'data."identity.pub"' | base64 --decode
|
yq read podinfo-auth.yaml 'data."identity.pub"' | base64 --decode
|
||||||
|
|
||||||
@@ -61,7 +63,7 @@ For Git over HTTP/S, the provided basic authentication credentials are stored in
|
|||||||
flux create secret git podinfo-auth \
|
flux create secret git podinfo-auth \
|
||||||
--namespace=apps \
|
--namespace=apps \
|
||||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||||
--export > podinfo-auth.yaml
|
--export > podinfo-auth.yaml
|
||||||
|
|
||||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||||
--in-place podinfo-auth.yaml
|
--in-place podinfo-auth.yaml
|
||||||
@@ -82,9 +84,9 @@ func init() {
|
|||||||
createSecretGitCmd.Flags().StringVar(&secretGitURL, "url", "", "git address, e.g. ssh://git@host/org/repository")
|
createSecretGitCmd.Flags().StringVar(&secretGitURL, "url", "", "git address, e.g. ssh://git@host/org/repository")
|
||||||
createSecretGitCmd.Flags().StringVarP(&secretGitUsername, "username", "u", "", "basic authentication username")
|
createSecretGitCmd.Flags().StringVarP(&secretGitUsername, "username", "u", "", "basic authentication username")
|
||||||
createSecretGitCmd.Flags().StringVarP(&secretGitPassword, "password", "p", "", "basic authentication password")
|
createSecretGitCmd.Flags().StringVarP(&secretGitPassword, "password", "p", "", "basic authentication password")
|
||||||
createSecretGitCmd.Flags().Var(&secretGitKeyAlgorithm, "ssh-key-algorithm", sourceGitKeyAlgorithm.Description())
|
createSecretGitCmd.Flags().Var(&secretGitKeyAlgorithm, "ssh-key-algorithm", secretGitKeyAlgorithm.Description())
|
||||||
createSecretGitCmd.Flags().Var(&secretGitRSABits, "ssh-rsa-bits", sourceGitRSABits.Description())
|
createSecretGitCmd.Flags().Var(&secretGitRSABits, "ssh-rsa-bits", secretGitRSABits.Description())
|
||||||
createSecretGitCmd.Flags().Var(&secretGitECDSACurve, "ssh-ecdsa-curve", sourceGitECDSACurve.Description())
|
createSecretGitCmd.Flags().Var(&secretGitECDSACurve, "ssh-ecdsa-curve", secretGitECDSACurve.Description())
|
||||||
|
|
||||||
createSecretCmd.AddCommand(createSecretGitCmd)
|
createSecretCmd.AddCommand(createSecretGitCmd)
|
||||||
}
|
}
|
||||||
@@ -122,7 +124,7 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
switch u.Scheme {
|
switch u.Scheme {
|
||||||
case "ssh":
|
case "ssh":
|
||||||
pair, err := generateKeyPair(ctx)
|
pair, err := generateKeyPair(ctx, secretGitKeyAlgorithm, secretGitRSABits, secretGitECDSACurve)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -171,3 +173,34 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateKeyPair(ctx context.Context, alg flags.PublicKeyAlgorithm, rsa flags.RSAKeyBits, ecdsa flags.ECDSACurve) (*ssh.KeyPair, error) {
|
||||||
|
var keyGen ssh.KeyPairGenerator
|
||||||
|
switch algorithm := alg.String(); algorithm {
|
||||||
|
case "rsa":
|
||||||
|
keyGen = ssh.NewRSAGenerator(int(rsa))
|
||||||
|
case "ecdsa":
|
||||||
|
keyGen = ssh.NewECDSAGenerator(ecdsa.Curve)
|
||||||
|
case "ed25519":
|
||||||
|
keyGen = ssh.NewEd25519Generator()
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported public key algorithm: %s", algorithm)
|
||||||
|
}
|
||||||
|
pair, err := keyGen.Generate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("key pair generation failed, error: %w", err)
|
||||||
|
}
|
||||||
|
return pair, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanHostKey(ctx context.Context, url *url.URL) ([]byte, error) {
|
||||||
|
host := url.Host
|
||||||
|
if url.Port() == "" {
|
||||||
|
host = host + ":22"
|
||||||
|
}
|
||||||
|
hostKey, err := ssh.ScanHostKey(host, 30*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("SSH key scan for host %s failed, error: %w", host, err)
|
||||||
|
}
|
||||||
|
return hostKey, nil
|
||||||
|
}
|
||||||
|
|||||||
141
cmd/flux/create_secret_helm.go
Normal file
141
cmd/flux/create_secret_helm.go
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var createSecretHelmCmd = &cobra.Command{
|
||||||
|
Use: "helm [name]",
|
||||||
|
Short: "Create or update a Kubernetes secret for Helm repository authentication",
|
||||||
|
Long: `
|
||||||
|
The create secret helm command generates a Kubernetes secret with basic authentication credentials.`,
|
||||||
|
Example: ` # Create a Helm authentication secret on disk and encrypt it with Mozilla SOPS
|
||||||
|
|
||||||
|
flux create secret helm repo-auth \
|
||||||
|
--namespace=my-namespace \
|
||||||
|
--username=my-username \
|
||||||
|
--password=my-password \
|
||||||
|
--export > repo-auth.yaml
|
||||||
|
|
||||||
|
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||||
|
--in-place repo-auth.yaml
|
||||||
|
|
||||||
|
# Create an authentication secret using a custom TLS cert
|
||||||
|
flux create secret helm repo-auth \
|
||||||
|
--username=username \
|
||||||
|
--password=password \
|
||||||
|
--cert-file=./cert.crt \
|
||||||
|
--key-file=./key.crt \
|
||||||
|
--ca-file=./ca.crt
|
||||||
|
`,
|
||||||
|
RunE: createSecretHelmCmdRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
secretHelmUsername string
|
||||||
|
secretHelmPassword string
|
||||||
|
secretHelmCertFile string
|
||||||
|
secretHelmKeyFile string
|
||||||
|
secretHelmCAFile string
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
createSecretHelmCmd.Flags().StringVarP(&secretHelmUsername, "username", "u", "", "basic authentication username")
|
||||||
|
createSecretHelmCmd.Flags().StringVarP(&secretHelmPassword, "password", "p", "", "basic authentication password")
|
||||||
|
createSecretHelmCmd.Flags().StringVar(&secretHelmCertFile, "cert-file", "", "TLS authentication cert file path")
|
||||||
|
createSecretHelmCmd.Flags().StringVar(&secretHelmKeyFile, "key-file", "", "TLS authentication key file path")
|
||||||
|
createSecretHelmCmd.Flags().StringVar(&secretHelmCAFile, "ca-file", "", "TLS authentication CA file path")
|
||||||
|
|
||||||
|
createSecretCmd.AddCommand(createSecretHelmCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return fmt.Errorf("secret name is required")
|
||||||
|
}
|
||||||
|
name := args[0]
|
||||||
|
|
||||||
|
secretLabels, err := parseLabels()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
secret := corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
Labels: secretLabels,
|
||||||
|
},
|
||||||
|
StringData: map[string]string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
if secretHelmUsername != "" && secretHelmPassword != "" {
|
||||||
|
secret.StringData["username"] = secretHelmUsername
|
||||||
|
secret.StringData["password"] = secretHelmPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
if secretHelmCertFile != "" && secretHelmKeyFile != "" {
|
||||||
|
cert, err := ioutil.ReadFile(secretHelmCertFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read repository cert file '%s': %w", secretHelmCertFile, err)
|
||||||
|
}
|
||||||
|
secret.StringData["certFile"] = string(cert)
|
||||||
|
|
||||||
|
key, err := ioutil.ReadFile(secretHelmKeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read repository key file '%s': %w", secretHelmKeyFile, err)
|
||||||
|
}
|
||||||
|
secret.StringData["keyFile"] = string(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if secretHelmCAFile != "" {
|
||||||
|
ca, err := ioutil.ReadFile(secretHelmCAFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read repository CA file '%s': %w", secretHelmCAFile, err)
|
||||||
|
}
|
||||||
|
secret.StringData["caFile"] = string(ca)
|
||||||
|
}
|
||||||
|
|
||||||
|
if export {
|
||||||
|
return exportSecret(secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := upsertSecret(ctx, kubeClient, secret); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Actionf("secret '%s' created in '%s' namespace", name, namespace)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -23,13 +23,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/fluxcd/flux2/internal/flags"
|
|
||||||
"github.com/fluxcd/flux2/internal/utils"
|
|
||||||
"github.com/fluxcd/pkg/apis/meta"
|
|
||||||
|
|
||||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
|
||||||
"github.com/manifoldco/promptui"
|
"github.com/manifoldco/promptui"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@@ -40,7 +34,10 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
"github.com/fluxcd/pkg/ssh"
|
"github.com/fluxcd/flux2/internal/flags"
|
||||||
|
"github.com/fluxcd/flux2/internal/utils"
|
||||||
|
"github.com/fluxcd/pkg/apis/meta"
|
||||||
|
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var createSourceGitCmd = &cobra.Command{
|
var createSourceGitCmd = &cobra.Command{
|
||||||
@@ -195,7 +192,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
withAuth = true
|
withAuth = true
|
||||||
} else if u.Scheme == "ssh" {
|
} else if u.Scheme == "ssh" {
|
||||||
logger.Generatef("generating deploy key pair")
|
logger.Generatef("generating deploy key pair")
|
||||||
pair, err := generateKeyPair(ctx)
|
pair, err := generateKeyPair(ctx, sourceGitKeyAlgorithm, sourceGitRSABits, sourceGitECDSACurve)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -288,63 +285,6 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateKeyPair(ctx context.Context) (*ssh.KeyPair, error) {
|
|
||||||
var keyGen ssh.KeyPairGenerator
|
|
||||||
switch algorithm := sourceGitKeyAlgorithm.String(); algorithm {
|
|
||||||
case "rsa":
|
|
||||||
keyGen = ssh.NewRSAGenerator(int(sourceGitRSABits))
|
|
||||||
case "ecdsa":
|
|
||||||
keyGen = ssh.NewECDSAGenerator(sourceGitECDSACurve.Curve)
|
|
||||||
case "ed25519":
|
|
||||||
keyGen = ssh.NewEd25519Generator()
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unsupported public key algorithm: %s", algorithm)
|
|
||||||
}
|
|
||||||
pair, err := keyGen.Generate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("key pair generation failed, error: %w", err)
|
|
||||||
}
|
|
||||||
return pair, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanHostKey(ctx context.Context, url *url.URL) ([]byte, error) {
|
|
||||||
host := url.Host
|
|
||||||
if url.Port() == "" {
|
|
||||||
host = host + ":22"
|
|
||||||
}
|
|
||||||
hostKey, err := ssh.ScanHostKey(host, 30*time.Second)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("SSH key scan for host %s failed, error: %w", host, err)
|
|
||||||
}
|
|
||||||
return hostKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func upsertSecret(ctx context.Context, kubeClient client.Client, secret corev1.Secret) error {
|
|
||||||
namespacedName := types.NamespacedName{
|
|
||||||
Namespace: secret.GetNamespace(),
|
|
||||||
Name: secret.GetName(),
|
|
||||||
}
|
|
||||||
|
|
||||||
var existing corev1.Secret
|
|
||||||
err := kubeClient.Get(ctx, namespacedName, &existing)
|
|
||||||
if err != nil {
|
|
||||||
if errors.IsNotFound(err) {
|
|
||||||
if err := kubeClient.Create(ctx, &secret); err != nil {
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
existing.StringData = secret.StringData
|
|
||||||
if err := kubeClient.Update(ctx, &existing); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func upsertGitRepository(ctx context.Context, kubeClient client.Client,
|
func upsertGitRepository(ctx context.Context, kubeClient client.Client,
|
||||||
gitRepository *sourcev1.GitRepository) (types.NamespacedName, error) {
|
gitRepository *sourcev1.GitRepository) (types.NamespacedName, error) {
|
||||||
namespacedName := types.NamespacedName{
|
namespacedName := types.NamespacedName{
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
components := append(installDefaultComponents, installExtraComponents...)
|
components := append(installDefaultComponents, installExtraComponents...)
|
||||||
|
|
||||||
|
if err := utils.ValidateComponents(components); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
opts := install.Options{
|
opts := install.Options{
|
||||||
BaseURL: installManifestsPath,
|
BaseURL: installManifestsPath,
|
||||||
Version: installVersion,
|
Version: installVersion,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ command -v flux >/dev/null && . <(flux completion zsh) && compdef _flux flux
|
|||||||
or write a cached file in one of the completion directories in your ${fpath}:
|
or write a cached file in one of the completion directories in your ${fpath}:
|
||||||
|
|
||||||
echo "${fpath// /\n}" | grep -i completion
|
echo "${fpath// /\n}" | grep -i completion
|
||||||
flux completions zsh > _flux
|
flux completion zsh > _flux
|
||||||
|
|
||||||
mv _flux ~/.oh-my-zsh/completions # oh-my-zsh
|
mv _flux ~/.oh-my-zsh/completions # oh-my-zsh
|
||||||
mv _flux ~/.zprezto/modules/completion/external/src/ # zprezto
|
mv _flux ~/.zprezto/modules/completion/external/src/ # zprezto
|
||||||
|
|||||||
@@ -29,4 +29,5 @@ The create source sub-commands generate Kubernetes secrets specific to Flux.
|
|||||||
|
|
||||||
* [flux create](flux_create.md) - Create or update sources and resources
|
* [flux create](flux_create.md) - Create or update sources and resources
|
||||||
* [flux create secret git](flux_create_secret_git.md) - Create or update a Kubernetes secret for Git authentication
|
* [flux create secret git](flux_create_secret_git.md) - Create or update a Kubernetes secret for Git authentication
|
||||||
|
* [flux create secret helm](flux_create_secret_helm.md) - Create or update a Kubernetes secret for Helm repository authentication
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ flux create secret git [name] [flags]
|
|||||||
# Create a Git SSH secret on disk and print the deploy key
|
# Create a Git SSH secret on disk and print the deploy key
|
||||||
flux create secret git podinfo-auth \
|
flux create secret git podinfo-auth \
|
||||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||||
--export > podinfo-auth.yaml
|
--export > podinfo-auth.yaml
|
||||||
|
|
||||||
yq read podinfo-auth.yaml 'data."identity.pub"' | base64 --decode
|
yq read podinfo-auth.yaml 'data."identity.pub"' | base64 --decode
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ flux create secret git [name] [flags]
|
|||||||
flux create secret git podinfo-auth \
|
flux create secret git podinfo-auth \
|
||||||
--namespace=apps \
|
--namespace=apps \
|
||||||
--url=ssh://git@github.com/stefanprodan/podinfo \
|
--url=ssh://git@github.com/stefanprodan/podinfo \
|
||||||
--export > podinfo-auth.yaml
|
--export > podinfo-auth.yaml
|
||||||
|
|
||||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||||
--in-place podinfo-auth.yaml
|
--in-place podinfo-auth.yaml
|
||||||
|
|||||||
65
docs/cmd/flux_create_secret_helm.md
Normal file
65
docs/cmd/flux_create_secret_helm.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
## flux create secret helm
|
||||||
|
|
||||||
|
Create or update a Kubernetes secret for Helm repository authentication
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
|
||||||
|
The create secret helm command generates a Kubernetes secret with basic authentication credentials.
|
||||||
|
|
||||||
|
```
|
||||||
|
flux create secret helm [name] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
# Create a Helm authentication secret on disk and encrypt it with Mozilla SOPS
|
||||||
|
|
||||||
|
flux create secret helm repo-auth \
|
||||||
|
--namespace=my-namespace \
|
||||||
|
--username=my-username \
|
||||||
|
--password=my-password \
|
||||||
|
--export > repo-auth.yaml
|
||||||
|
|
||||||
|
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||||
|
--in-place repo-auth.yaml
|
||||||
|
|
||||||
|
# Create an authentication secret using a custom TLS cert
|
||||||
|
flux create secret helm repo-auth \
|
||||||
|
--username=username \
|
||||||
|
--password=password \
|
||||||
|
--cert-file=./cert.crt \
|
||||||
|
--key-file=./key.crt \
|
||||||
|
--ca-file=./ca.crt
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
--ca-file string TLS authentication CA file path
|
||||||
|
--cert-file string TLS authentication cert file path
|
||||||
|
-h, --help help for helm
|
||||||
|
--key-file string TLS authentication key file path
|
||||||
|
-p, --password string basic authentication password
|
||||||
|
-u, --username string basic authentication username
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
--context string kubernetes context to use
|
||||||
|
--export export in YAML format to stdout
|
||||||
|
--interval duration source sync interval (default 1m0s)
|
||||||
|
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
|
||||||
|
--label strings set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)
|
||||||
|
-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 create secret](flux_create_secret.md) - Create or update Kubernetes secrets
|
||||||
|
|
||||||
52
docs/core-concepts/index.md
Normal file
52
docs/core-concepts/index.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Core Concepts
|
||||||
|
|
||||||
|
!!! note "Work in progress"
|
||||||
|
This document is a work in progress.
|
||||||
|
|
||||||
|
These are some core concepts in Flux.
|
||||||
|
|
||||||
|
## GitOps
|
||||||
|
|
||||||
|
GitOps is a way of managing your infrastructure and applications so that whole system is described declaratively and version controlled (most likely in a Git repository), and having an automated process that ensures that the deployed environment matches the state specified in a repository.
|
||||||
|
|
||||||
|
For more information, take a look at ["What is GitOps?"](https://www.gitops.tech/#what-is-gitops).
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
A *Source* defines the origin of a source and the requirements to obtain
|
||||||
|
it (e.g. credentials, version selectors). For example, the latest `1.x` tag
|
||||||
|
available from a Git repository over SSH.
|
||||||
|
|
||||||
|
Sources produce an artifact that is consumed by other Flux elements to perform
|
||||||
|
actions, like applying the contents of the artifact on the cluster. A source
|
||||||
|
may be shared by multiple consumers to deduplicate configuration and/or storage.
|
||||||
|
|
||||||
|
The origin of the source is checked for changes on a defined interval, if
|
||||||
|
there is a newer version available that matches the criteria, a new artifact
|
||||||
|
is produced.
|
||||||
|
|
||||||
|
All sources are specified as Custom Resources in a Kubernetes cluster, examples
|
||||||
|
of sources are `GitRepository`, `HelmRepository` and `Bucket` resources.
|
||||||
|
|
||||||
|
For more information, take a look at [the source controller documentation](../components/source/source.md).
|
||||||
|
|
||||||
|
## Reconciliation
|
||||||
|
|
||||||
|
Reconciliation refers to ensuring that a given state (e.g application running in the cluster, infrastructure) matches a desired state declaratively defined somewhere (e.g a git repository). There are various examples of these in flux e.g:
|
||||||
|
|
||||||
|
- HelmRelease reconciliation: ensures the state of the Helm release matches what is defined in the resource, performs a release if this is not the case (including revision changes of a HelmChart resource).
|
||||||
|
- Bucket reconciliation: downloads and archives the contents of the declared bucket on a given interval and stores this as an artifact, records the observed revision of the artifact and the artifact itself in the status of resource.
|
||||||
|
- [Kustomization](#kustomization) reconciliation: ensures the state of the application deployed on a cluster matches resources contained in a git repository.
|
||||||
|
|
||||||
|
## Kustomization
|
||||||
|
|
||||||
|
The kustomization represents a local set of Kubernetes resources that Flux is supposed to reconcile in the cluster. The reconciliation runs every one minute by default but this can be specified in the kustomization. If you make any changes to the cluster using `kubectl edit` or `kubectl patch`, it will be promptly reverted. You either suspend the reconciliation or push your changes to a Git repository.
|
||||||
|
|
||||||
|
For more information, take a look at [this documentation](../components/kustomize/kustomization.md).
|
||||||
|
|
||||||
|
## Bootstrap
|
||||||
|
|
||||||
|
The process of installing the Flux components in a complete GitOps way is called a bootstrap. The manifests are applied to the cluster, a `GitRepository` and `Kustomization` are created for the Flux components, and the manifests are pushed to an existing Git repository (or a new one is created). Flux can manage itself just as it manages other resources.
|
||||||
|
The bootstrap is done using the `flux` CLI `flux bootstrap`.
|
||||||
|
|
||||||
|
For more information, take a look at [the documentation for the bootstrap command](../cmd/flux_bootstrap.md).
|
||||||
@@ -17,7 +17,7 @@ On your dev machine install the following tools:
|
|||||||
* kustomize >= 3.5
|
* kustomize >= 3.5
|
||||||
* docker >= 19.03
|
* docker >= 19.03
|
||||||
|
|
||||||
## Install the GitOps Toolkit
|
## Install Flux
|
||||||
|
|
||||||
Create a cluster for testing:
|
Create a cluster for testing:
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ Create a cluster for testing:
|
|||||||
kind create cluster --name dev
|
kind create cluster --name dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Install the toolkit CLI:
|
Install the Flux CLI:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -s https://toolkit.fluxcd.io/install.sh | sudo bash
|
curl -s https://toolkit.fluxcd.io/install.sh | sudo bash
|
||||||
@@ -37,7 +37,7 @@ Verify that your dev machine satisfies the prerequisites with:
|
|||||||
flux check --pre
|
flux check --pre
|
||||||
```
|
```
|
||||||
|
|
||||||
Install the toolkit controllers on the dev cluster:
|
Install source-controller on the dev cluster:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
flux install
|
flux install
|
||||||
@@ -45,13 +45,13 @@ flux install
|
|||||||
|
|
||||||
## Clone the sample controller
|
## Clone the sample controller
|
||||||
|
|
||||||
You'll be using [stefanprodan/source-watcher](https://github.com/stefanprodan/source-watcher) as
|
You'll be using [fluxcd/source-watcher](https://github.com/fluxcd/source-watcher) as
|
||||||
a template for developing your own controller. The source-watcher was scaffolded with `kubebuilder init`.
|
a template for developing your own controller. The source-watcher was scaffolded with `kubebuilder init`.
|
||||||
|
|
||||||
Clone the source-watcher repo:
|
Clone the source-watcher repository:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/stefanprodan/source-watcher
|
git clone https://github.com/fluxcd/source-watcher
|
||||||
cd source-watcher
|
cd source-watcher
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ The source-controller reports the revision under `GitRepository.Status.Artifact.
|
|||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
The [GitRepositoryWatcher](https://github.com/stefanprodan/source-watcher/blob/master/controllers/gitrepository_watcher.go)
|
The [GitRepositoryWatcher](https://github.com/fluxcd/source-watcher/blob/main/controllers/gitrepository_watcher.go)
|
||||||
controller does the following:
|
controller does the following:
|
||||||
|
|
||||||
* subscribes to `GitRepository` events
|
* subscribes to `GitRepository` events
|
||||||
@@ -186,8 +186,8 @@ func (r *GitRepositoryWatcher) SetupWithManager(mgr ctrl.Manager) error {
|
|||||||
|
|
||||||
To add the watcher to an existing project, copy the controller and the revision change predicate to your `controllers` dir:
|
To add the watcher to an existing project, copy the controller and the revision change predicate to your `controllers` dir:
|
||||||
|
|
||||||
* [gitrepository_watcher.go](https://github.com/stefanprodan/source-watcher/blob/master/controllers/gitrepository_watcher.go)
|
* [gitrepository_watcher.go](https://github.com/fluxcd/source-watcher/blob/main/controllers/gitrepository_watcher.go)
|
||||||
* [gitrepository_predicate.go](https://github.com/stefanprodan/source-watcher/blob/master/controllers/gitrepository_predicate.go)
|
* [gitrepository_predicate.go](https://github.com/fluxcd/source-watcher/blob/main/controllers/gitrepository_predicate.go)
|
||||||
|
|
||||||
In your `main.go` init function, register the Source API schema:
|
In your `main.go` init function, register the Source API schema:
|
||||||
|
|
||||||
@@ -224,9 +224,9 @@ Your `go.mod` should require controller-runtime v0.6 or newer:
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
require (
|
require (
|
||||||
k8s.io/apimachinery v0.18.4
|
k8s.io/apimachinery v0.19.4
|
||||||
k8s.io/client-go v0.18.4
|
k8s.io/client-go v0.19.4
|
||||||
sigs.k8s.io/controller-runtime v0.6.0
|
sigs.k8s.io/controller-runtime v0.6.4
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
# Get started with Flux v2
|
# Get started with Flux v2
|
||||||
|
|
||||||
|
!!! note "Basic knowledge"
|
||||||
|
This guide assumes you have some understanding of the core concepts and have read the introduction to Flux.
|
||||||
|
The core concepts used in this guide are [GitOps](../core-concepts/index.md#gitops), [Sources](../core-concepts/index.md#sources), [Kustomization](../core-concepts/index.md#kustomization).
|
||||||
|
|
||||||
|
In this tutorial, you will deploy an application to a kubernetes cluster with Flux and manage the cluster in a complete GitOps manner. You'll be using a dedicated Git repository e.g. `fleet-infra` to manage the Kubernetes clusters. All the manifest will be pushed to this repository and then applied by Flux.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
You will need two Kubernetes clusters version 1.16 or newer and kubectl version 1.18.
|
In order to follow the guide, you will need one Kubernetes cluster version 1.16 or newer and kubectl version 1.18.
|
||||||
For a quick local test, you can use [Kubernetes kind](https://kind.sigs.k8s.io/docs/user/quick-start/).
|
For a quick local test, you can use [Kubernetes kind](https://kind.sigs.k8s.io/docs/user/quick-start/).
|
||||||
Any other Kubernetes setup will work as well though.
|
Any other Kubernetes setup will work as well though.
|
||||||
|
|
||||||
In order to follow the guide you'll need a GitHub account and a
|
Flux is installed in a complete GitOps way and its manifest will be pushed to the repository, so you will also need a GitHub account and a
|
||||||
[personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)
|
[personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)
|
||||||
that can create repositories (check all permissions under `repo`).
|
that can create repositories (check all permissions under `repo`) to enable Flux do this.
|
||||||
|
|
||||||
Export your GitHub personal access token and username:
|
Export your GitHub personal access token and username:
|
||||||
|
|
||||||
@@ -52,24 +58,13 @@ profile:
|
|||||||
|
|
||||||
`zsh`, `fish`, and `powershell` are also supported with their own sub-commands.
|
`zsh`, `fish`, and `powershell` are also supported with their own sub-commands.
|
||||||
|
|
||||||
## GitOps workflow
|
## Install Flux components
|
||||||
|
|
||||||
You'll be using a dedicated Git repository e.g. `fleet-infra` to manage one or more Kubernetes clusters.
|
Create the cluster using Kubernetes kind or set the kubectl context to an existing cluster:
|
||||||
This guide assumes that you have two clusters, one for staging and one for production.
|
|
||||||
|
|
||||||
Using the Flux CLI you'll do the following:
|
|
||||||
|
|
||||||
- configure each cluster to synchronise with a directory inside the fleet repository
|
|
||||||
- register app sources (git repositories) that contain plain Kubernetes manifests or Kustomize overlays
|
|
||||||
- configure app deployments on both clusters (pre-releases on staging, semver releases on production)
|
|
||||||
|
|
||||||
## Staging bootstrap
|
|
||||||
|
|
||||||
Create the staging cluster using Kubernetes kind or set the kubectl context to an existing cluster:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
kind create cluster --name staging
|
kind create cluster
|
||||||
kubectl cluster-info --context kind-staging
|
kubectl cluster-info --context kind-kind
|
||||||
```
|
```
|
||||||
|
|
||||||
Verify that your staging cluster satisfies the prerequisites with:
|
Verify that your staging cluster satisfies the prerequisites with:
|
||||||
@@ -89,7 +84,7 @@ flux bootstrap github \
|
|||||||
--owner=$GITHUB_USER \
|
--owner=$GITHUB_USER \
|
||||||
--repository=fleet-infra \
|
--repository=fleet-infra \
|
||||||
--branch=main \
|
--branch=main \
|
||||||
--path=staging-cluster \
|
--path=./clusters/my-cluster \
|
||||||
--personal
|
--personal
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -98,8 +93,8 @@ flux bootstrap github \
|
|||||||
you can use `--arch=arm` for ARMv7 32-bit container images
|
you can use `--arch=arm` for ARMv7 32-bit container images
|
||||||
and `--arch=arm64` for ARMv8 64-bit container images.
|
and `--arch=arm64` for ARMv8 64-bit container images.
|
||||||
|
|
||||||
The bootstrap command creates a repository if one doesn't exist, and
|
The bootstrap command creates a repository if one doesn't exist,
|
||||||
commits the manifests for the Flux components to the default branch at the specified path.
|
commits the manifests for the Flux components to the default branch at the specified path, and installs the Flux components.
|
||||||
Then it configures the target cluster to synchronize with the specified path inside the repository.
|
Then it configures the target cluster to synchronize with the specified path inside the repository.
|
||||||
|
|
||||||
If you wish to create the repository under a GitHub organization:
|
If you wish to create the repository under a GitHub organization:
|
||||||
@@ -111,7 +106,7 @@ flux bootstrap github \
|
|||||||
--branch=<organization default branch> \
|
--branch=<organization default branch> \
|
||||||
--team=<team1-slug> \
|
--team=<team1-slug> \
|
||||||
--team=<team2-slug> \
|
--team=<team2-slug> \
|
||||||
--path=staging-cluster
|
--path=./clusters/my-cluster
|
||||||
```
|
```
|
||||||
|
|
||||||
Example output:
|
Example output:
|
||||||
@@ -148,102 +143,104 @@ If you prefer GitLab, export `GITLAB_TOKEN` env var and use the command [flux bo
|
|||||||
You can target a specific Flux [version](https://github.com/fluxcd/flux2/releases)
|
You can target a specific Flux [version](https://github.com/fluxcd/flux2/releases)
|
||||||
with `flux bootstrap --version=<semver>`.
|
with `flux bootstrap --version=<semver>`.
|
||||||
|
|
||||||
## Staging workflow
|
## Clone the git repository
|
||||||
|
|
||||||
Clone the repository with:
|
We are going to be managing the application in a GitOps manner with the git repository. The Flux manifests generated by the CLI will be pushed to the git repository. Instead of applying the manifests directly to the cluster, Flux will apply it for us instead :).
|
||||||
|
|
||||||
|
Therefore, we need to clone the repository to our local machine.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/$GITHUB_USER/fleet-infra
|
git clone https://github.com/$GITHUB_USER/fleet-infra
|
||||||
cd fleet-infra
|
cd fleet-infra
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a git source pointing to a public repository master branch:
|
|
||||||
|
## Add podinfo repository to Flux
|
||||||
|
|
||||||
|
We will be using a public repository [github.com/stefanprodan/podinfo](https://github.com/stefanprodan/podinfo), podinfo is a tiny web application made with Go.
|
||||||
|
|
||||||
|
Create a GitRepository manifest pointing to the repository's master branch with Flux CLI.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
flux create source git webapp \
|
flux create source git podinfo \
|
||||||
--url=https://github.com/stefanprodan/podinfo \
|
--url=https://github.com/stefanprodan/podinfo \
|
||||||
--branch=master \
|
--branch=master \
|
||||||
--interval=30s \
|
--interval=30s \
|
||||||
--export > ./staging-cluster/webapp-source.yaml
|
--export > ./clusters/my-cluster/podinfo-source.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a kustomization for synchronizing the common manifests on the cluster:
|
Commit and push it to the `fleet-infra` repository, then Flux applies it to the cluster.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
flux create kustomization webapp-common \
|
git add -A && git commit -m "Adds podinfo git source"
|
||||||
--source=webapp \
|
git push
|
||||||
--path="./deploy/webapp/common" \
|
```
|
||||||
|
|
||||||
|
## Deploy podinfo application
|
||||||
|
|
||||||
|
We will create a kustomization manifest for podinfo. This will apply the manifest in the `kustomize` directory in the podinfo repository.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
flux create kustomization podinfo \
|
||||||
|
--source=podinfo \
|
||||||
|
--path="./kustomize" \
|
||||||
--prune=true \
|
--prune=true \
|
||||||
--validation=client \
|
--validation=client \
|
||||||
--interval=1h \
|
--interval=5m \
|
||||||
--export > ./staging-cluster/webapp-common.yaml
|
--export > ./clusters/my-cluster/podinfo-kustomization.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a kustomization for the backend service that depends on common:
|
Commit and push the kustomization manifest to the git repository so that Flux applies it to the cluster.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
flux create kustomization webapp-backend \
|
git add -A && git commit -m "Adds podinfo kustomization"
|
||||||
--depends-on=webapp-common \
|
git push
|
||||||
--source=webapp \
|
|
||||||
--path="./deploy/webapp/backend" \
|
|
||||||
--prune=true \
|
|
||||||
--validation=client \
|
|
||||||
--interval=10m \
|
|
||||||
--health-check="Deployment/backend.webapp" \
|
|
||||||
--health-check-timeout=2m \
|
|
||||||
--export > ./staging-cluster/webapp-backend.yaml
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a kustomization for the frontend service that depends on backend:
|
The structure of your repository should look like this:
|
||||||
|
```
|
||||||
```sh
|
fleet-infra
|
||||||
flux create kustomization webapp-frontend \
|
└── clusters/
|
||||||
--depends-on=webapp-backend \
|
└── my-cluster/
|
||||||
--source=webapp \
|
├── flux-system/
|
||||||
--path="./deploy/webapp/frontend" \
|
│ ├── gotk-components.yaml/
|
||||||
--prune=true \
|
│ ├── gotk-sync.yaml/
|
||||||
--validation=client \
|
│ └── kustomization.yaml/
|
||||||
--interval=10m \
|
├── podinfo-kustomization.yaml
|
||||||
--health-check="Deployment/frontend.webapp" \
|
└── podinfo-source.yaml
|
||||||
--health-check-timeout=2m \
|
|
||||||
--export > ./staging-cluster/webapp-frontend.yaml
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Push changes to origin:
|
|
||||||
|
|
||||||
```sh
|
## Watch Flux sync the application
|
||||||
git add -A && git commit -m "add staging webapp" && git push
|
|
||||||
```
|
|
||||||
|
|
||||||
In about 30s the synchronization should start:
|
In about 30s the synchronization should start:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ watch flux get kustomizations
|
$ watch flux get kustomizations
|
||||||
NAME READY MESSAGE
|
NAME READY MESSAGE
|
||||||
flux-system True Applied revision: main/6eea299fe9997c8561b826b67950afaf9a476cf8
|
flux-system main/fc07af652d3168be329539b30a4c3943a7d12dd8 False True Applied revision: main/fc07af652d3168be329539b30a4c3943a7d12dd8
|
||||||
webapp-backend False dependency 'flux-system/webapp-common' is not ready
|
podinfo master/855f7724be13f6146f61a893851522837ad5b634 False True Applied revision: master/855f7724be13f6146f61a893851522837ad5b634
|
||||||
webapp-common True Applied revision: master/7411da595c25183daba255068814b83843fe3395
|
|
||||||
webapp-frontend False dependency 'flux-system/webapp-backend' is not ready
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When the synchronization finishes you can check that the webapp services are running:
|
When the synchronization finishes you can check that the podinfo has been deployed on your cluster:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ kubectl -n webapp get deployments,services
|
$ kubectl -n default get deployments,services
|
||||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||||
deployment.apps/backend 1/1 1 1 4m1s
|
deployment.apps/podinfo 2/2 2 2 108s
|
||||||
deployment.apps/frontend 1/1 1 1 3m31s
|
|
||||||
|
|
||||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||||
service/backend ClusterIP 10.52.10.22 <none> 9898/TCP,9999/TCP 4m1s
|
service/podinfo ClusterIP 10.100.149.126 <none> 9898/TCP,9999/TCP 108s
|
||||||
service/frontend ClusterIP 10.52.9.85 <none> 80/TCP 3m31s
|
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tip
|
!!! tip
|
||||||
From this moment forward, any changes made to the webapp
|
From this moment forward, any changes made to the webapp
|
||||||
Kubernetes manifests in the master branch will be synchronised with the staging cluster.
|
Kubernetes manifests in the master branch will be synchronised with your cluster.
|
||||||
|
|
||||||
If a Kubernetes manifest is removed from the webapp repository, the reconciler will remove it from your cluster.
|
If a Kubernetes manifest is removed from the webapp repository, the reconciler will remove it from your cluster.
|
||||||
|
If you delete a kustomization from the cluster, the reconciler will remove all Kubernetes objects that
|
||||||
|
were previously applied from that kustomization.
|
||||||
|
|
||||||
If you delete a kustomization from the `fleet-infra` repo, the reconciler will remove all Kubernetes objects that
|
If you delete a kustomization from the `fleet-infra` repo, the reconciler will remove all Kubernetes objects that
|
||||||
were previously applied from that kustomization.
|
were previously applied from that kustomization.
|
||||||
|
|
||||||
@@ -252,121 +249,10 @@ the state described in git. When dealing with an incident, you can pause the rec
|
|||||||
kustomization with `flux suspend kustomization <name>`. Once the debugging session
|
kustomization with `flux suspend kustomization <name>`. Once the debugging session
|
||||||
is over, you can re-enable the reconciliation with `flux resume kustomization <name>`.
|
is over, you can re-enable the reconciliation with `flux resume kustomization <name>`.
|
||||||
|
|
||||||
## Production bootstrap
|
## Multi-cluster Setup
|
||||||
|
|
||||||
On production clusters, you may wish to deploy stable releases of an application.
|
To use Flux to manage more than one cluster or promote deployments from staging to production, take a look at the
|
||||||
When creating a git source instead of a branch, you can specify a git tag or a semver expression.
|
two approaches in the repositories listed below.
|
||||||
|
|
||||||
Create the production cluster using Kubernetes kind or set the kubectl context to an existing cluster:
|
1. [https://github.com/fluxcd/flux2-kustomize-helm-example](https://github.com/fluxcd/flux2-kustomize-helm-example)
|
||||||
|
2. [https://github.com/fluxcd/flux2-multi-tenancy](https://github.com/fluxcd/flux2-multi-tenancy)
|
||||||
```sh
|
|
||||||
kind create cluster --name production
|
|
||||||
kubectl cluster-info --context kind-production
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the bootstrap for the production environment:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
flux bootstrap github \
|
|
||||||
--owner=$GITHUB_USER \
|
|
||||||
--repository=fleet-infra \
|
|
||||||
--path=prod-cluster \
|
|
||||||
--personal
|
|
||||||
```
|
|
||||||
Pull the changes locally:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git pull
|
|
||||||
```
|
|
||||||
|
|
||||||
## Production workflow
|
|
||||||
|
|
||||||
Create a git source using a semver range to target stable releases:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
flux create source git webapp \
|
|
||||||
--url=https://github.com/stefanprodan/podinfo \
|
|
||||||
--tag-semver=">=4.0.0 <4.0.2" \
|
|
||||||
--interval=30s \
|
|
||||||
--export > ./prod-cluster/webapp-source.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
Create a kustomization for webapp pointing to the production overlay:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
flux create kustomization webapp \
|
|
||||||
--source=webapp \
|
|
||||||
--path="./deploy/overlays/production" \
|
|
||||||
--prune=true \
|
|
||||||
--validation=client \
|
|
||||||
--interval=10m \
|
|
||||||
--health-check="Deployment/frontend.production" \
|
|
||||||
--health-check="Deployment/backend.production" \
|
|
||||||
--health-check-timeout=2m \
|
|
||||||
--export > ./prod-cluster/webapp-production.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
Push changes to origin:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git add -A && git commit -m "add prod webapp" && git push
|
|
||||||
```
|
|
||||||
|
|
||||||
List git sources:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ flux get sources git
|
|
||||||
NAME REVISION READY MESSAGE
|
|
||||||
flux-system main/5ae055e24b2c8a78f981708b61507a97a30bd7a6 True Fetched revision: main/113360052b3153e439a0cf8de76b8e3d2a7bdf27
|
|
||||||
webapp 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27 True Fetched revision: 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27
|
|
||||||
```
|
|
||||||
|
|
||||||
The kubectl equivalent is `kubectl -n flux-system get gitrepositories`.
|
|
||||||
|
|
||||||
List kustomization:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ flux get kustomizations
|
|
||||||
NAME REVISION SUSPENDED READY MESSAGE
|
|
||||||
flux-system main/5ae055e24b2c8a78f981708b61507a97a30bd7a6 False True Applied revision: main/5ae055e24b2c8a78f981708b61507a97a30bd7a6
|
|
||||||
webapp 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27 False True Applied revision: 4.0.1/113360052b3153e439a0cf8de76b8e3d2a7bdf27
|
|
||||||
```
|
|
||||||
|
|
||||||
The kubectl equivalent is `kubectl -n flux-system get kustomizations`.
|
|
||||||
|
|
||||||
If you want to upgrade to the latest 4.x version, you can change the semver expression to:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
flux create source git webapp \
|
|
||||||
--url=https://github.com/stefanprodan/podinfo \
|
|
||||||
--tag-semver=">=4.0.0 <5.0.0" \
|
|
||||||
--interval=30s \
|
|
||||||
--export > ./prod-cluster/webapp-source.yaml
|
|
||||||
|
|
||||||
git add -A && git commit -m "update prod webapp" && git push
|
|
||||||
```
|
|
||||||
|
|
||||||
Trigger a git sync:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ flux reconcile ks flux-system --with-source
|
|
||||||
► annotating source flux-system
|
|
||||||
✔ source annotated
|
|
||||||
◎ waiting for reconcilitation
|
|
||||||
✔ git reconciliation completed
|
|
||||||
✔ fetched revision main/d751ea264d48bf0db8b588d1d08184834ac8fec9
|
|
||||||
◎ waiting for kustomization reconcilitation
|
|
||||||
✔ kustomization reconcilitation completed
|
|
||||||
✔ applied revision main/d751ea264d48bf0db8b588d1d08184834ac8fec9
|
|
||||||
```
|
|
||||||
|
|
||||||
The kubectl equivalent is `kubectl -n flux-system annotate gitrepository/flux-system fluxcd.io/reconcileAt="$(date +%s)"`.
|
|
||||||
|
|
||||||
Wait for the webapp to be upgraded:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ watch flux get kustomizations
|
|
||||||
NAME REVISION SUSPENDED READY MESSAGE
|
|
||||||
flux-system main/d751ea264d48bf0db8b588d1d08184834ac8fec9 False True Applied revision: main/d751ea264d48bf0db8b588d1d08184834ac8fec9
|
|
||||||
webapp 4.0.6/26a630c0b4b3452833d96c511d93f6f2d2e90a99 False True Applied revision: 4.0.6/26a630c0b4b3452833d96c511d93f6f2d2e90a99
|
|
||||||
```
|
|
||||||
@@ -118,51 +118,78 @@ repository and omits all other files.
|
|||||||
Git repositories. See the [`GitRepository` CRD docs](../components/source/gitrepositories.md)
|
Git repositories. See the [`GitRepository` CRD docs](../components/source/gitrepositories.md)
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
### Bucket
|
### Cloud Storage
|
||||||
|
|
||||||
Charts from S3 compatible storage buckets can be released by declaring
|
It is inadvisable while still possible to use a `Bucket` as a source for a `HelmRelease`,
|
||||||
a `Bucket`, the source-controller will fetch the contents of the bucket
|
as the whole storage bucket will be downloaded by source controller at each sync. The
|
||||||
on an interval and expose it as an artifact.
|
bucket can easily become very large if there are frequent releases of multiple charts
|
||||||
|
that are stored in the same bucket.
|
||||||
|
|
||||||
**There is one caveat you should be aware of:** to make the
|
A better option is to use [Chartmuseum](https://github.com/helm/chartmuseum) and run a cluster
|
||||||
source-controller produce a new chart artifact, the `version` in the
|
local Helm repository that can be used by source controller. Chartmuseum has support
|
||||||
`Chart.yaml` of the chart must be bumped.
|
for multiple different cloud storage solutions such as S3, GCS, and Azure Blob Storage,
|
||||||
|
meaning that you are not limited to only using storage providers that support the S3 protocol.
|
||||||
|
|
||||||
An example `Bucket`:
|
You can deploy a Chartmuseum instance with a `HelmRelease` that exposes a Helm repository stored
|
||||||
|
in a S3 bucket. Please refer to [Chartmuseums how to run documentation](https://chartmuseum.com/docs/#how-to-run)
|
||||||
|
for details about how to use other storage backends.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||||
kind: Bucket
|
kind: HelmRepository
|
||||||
metadata:
|
metadata:
|
||||||
name: podinfo
|
name: chartmuseum
|
||||||
namespace: gotk-system
|
namespace: flux-system
|
||||||
spec:
|
spec:
|
||||||
interval: 1m
|
url: https://chartmuseum.github.io/charts
|
||||||
provider: generic
|
interval: 10m
|
||||||
bucketName: podinfo
|
---
|
||||||
endpoint: minio.minio.svc.cluster.local:9000
|
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||||
ignore: |
|
kind: HelmRelease
|
||||||
# exclude all
|
metadata:
|
||||||
/*
|
name: chartmuseum
|
||||||
# include charts directory
|
namespace: flux-system
|
||||||
!/charts/
|
spec:
|
||||||
|
interval: 5m
|
||||||
|
chart:
|
||||||
|
spec:
|
||||||
|
chart: chartmuseum
|
||||||
|
version: "2.14.2"
|
||||||
|
sourceRef:
|
||||||
|
kind: HelmRepository
|
||||||
|
name: chartmuseum
|
||||||
|
namespace: flux-system
|
||||||
|
interval: 1m
|
||||||
|
values:
|
||||||
|
env:
|
||||||
|
open:
|
||||||
|
AWS_SDK_LOAD_CONFIG: true
|
||||||
|
STORAGE: amazon
|
||||||
|
STORAGE_AMAZON_BUCKET: "bucket-name"
|
||||||
|
STORAGE_AMAZON_PREFIX: ""
|
||||||
|
STORAGE_AMAZON_REGION: "region-name"
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
annotations:
|
||||||
|
eks.amazonaws.com/role-arn: "role-arn"
|
||||||
|
securityContext:
|
||||||
|
enabled: true
|
||||||
|
fsGroup: 65534
|
||||||
```
|
```
|
||||||
|
|
||||||
The `interval` defines at which interval the Git repository contents
|
After Chartmuseum is up and running it should be possible to use the accompanying
|
||||||
are fetched, and should be at least `1m`. Setting this to a higher
|
service as the url for the `HelmRepository`.
|
||||||
value means newer chart versions will be detected at a slower pace,
|
|
||||||
a push-based fetch can be introduced using [webhook receivers](webhook-receivers.md)
|
|
||||||
|
|
||||||
The `provider`, `bucketName` and `endpoint` together define what
|
```yaml
|
||||||
S3 compatible storage should be connected to. For more information,
|
apiVersion: source.toolkit.fluxcd.io/v1beta1
|
||||||
see the [`Bucket` CRD docs](../components/source/buckets.md).
|
kind: HelmRepository
|
||||||
|
metadata:
|
||||||
|
name: helm-charts
|
||||||
The `ignore` defines file and folder exclusion for the
|
namespace: flux-system
|
||||||
artifact produced, and follows the [`.gitignore` pattern
|
spec:
|
||||||
format](https://git-scm.com/docs/gitignore#_pattern_format).
|
interval: 1m
|
||||||
The above example only includes the `charts` directory of the
|
url: http://chartmuseum-chartmuseum:8080
|
||||||
repository and omits all other files.
|
```
|
||||||
|
|
||||||
## Define a Helm release
|
## Define a Helm release
|
||||||
|
|
||||||
@@ -257,6 +284,11 @@ The definition of the listed keys is as follows:
|
|||||||
You can read more about the available formats and limitations in
|
You can read more about the available formats and limitations in
|
||||||
the [Helm documentation](https://helm.sh/docs/intro/using_helm/#the-format-and-limitations-of---set).
|
the [Helm documentation](https://helm.sh/docs/intro/using_helm/#the-format-and-limitations-of---set).
|
||||||
|
|
||||||
|
!!! warning "`TargetPath` and JSON values"
|
||||||
|
When using `TargetPath` in combination with a JSON string, the
|
||||||
|
[limitations are the same as while using `helm`](https://github.com/helm/helm/issues/5618),
|
||||||
|
and require you to escape the full JSON string (including `=`, `[`, `,`, `.`).
|
||||||
|
|
||||||
## Refer to values in `ConfigMaps` generated with Kustomize
|
## Refer to values in `ConfigMaps` generated with Kustomize
|
||||||
|
|
||||||
It is possible to use Kustomize [ConfigMap generator](https://kubectl.docs.kubernetes.io/references/kustomize/configmapgenerator/)
|
It is possible to use Kustomize [ConfigMap generator](https://kubectl.docs.kubernetes.io/references/kustomize/configmapgenerator/)
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ flux create image update flux-system \
|
|||||||
--author-name=fluxcdbot \
|
--author-name=fluxcdbot \
|
||||||
--author-email=fluxcdbot@users.noreply.github.com \
|
--author-email=fluxcdbot@users.noreply.github.com \
|
||||||
--commit-template="[ci skip] update image" \
|
--commit-template="[ci skip] update image" \
|
||||||
--export ./clusters/my-cluster/flux-system-automation.yaml
|
--export > ./clusters/my-cluster/flux-system-automation.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
The above command generates the following manifest:
|
The above command generates the following manifest:
|
||||||
@@ -358,3 +358,145 @@ images:
|
|||||||
newName: ghcr.io/stefanprodan/podinfo
|
newName: ghcr.io/stefanprodan/podinfo
|
||||||
newTag: 5.0.0 # {"$imagepolicy": "flux-system:podinfo:tag"}
|
newTag: 5.0.0 # {"$imagepolicy": "flux-system:podinfo:tag"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## ImageRepository cloud providers authentication
|
||||||
|
|
||||||
|
If relying on a cloud provider image repository, you might need to do some extra
|
||||||
|
work in order to configure the ImageRepository resource credentials. Here are
|
||||||
|
some common examples for the most popular cloud provider docker registries.
|
||||||
|
|
||||||
|
!!! warning "Workarounds"
|
||||||
|
The examples below are intended as workaround solutions until native
|
||||||
|
authentication mechanisms are implemented in Flux itself to support this in
|
||||||
|
a more straightforward manner.
|
||||||
|
|
||||||
|
### AWS Elastic Container Registry
|
||||||
|
|
||||||
|
The registry authentication credentials for ECR expire every 12 hours.
|
||||||
|
Considering this limitation, one needs to ensure the credentials are being
|
||||||
|
refreshed before expiration so that the controller can rely on them for
|
||||||
|
authentication.
|
||||||
|
|
||||||
|
The solution proposed is to create a cronjob that runs every 6 hours which would
|
||||||
|
re-create the `docker-registry` secret using a new token.
|
||||||
|
|
||||||
|
Edit and save the following snippet to a file
|
||||||
|
`./clusters/my-cluster/ecr-sync.yaml`, commit and push it to git.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: ecr-credentials-sync
|
||||||
|
namespace: flux-system
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- delete
|
||||||
|
- create
|
||||||
|
---
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: ecr-credentials-sync
|
||||||
|
namespace: flux-system
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: ecr-credentials-sync
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: ecr-credentials-sync
|
||||||
|
apiGroup: ""
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: ecr-credentials-sync
|
||||||
|
# Uncomment and edit if using IRSA
|
||||||
|
# annotations:
|
||||||
|
# eks.amazonaws.com/role-arn: <role arn>
|
||||||
|
---
|
||||||
|
apiVersion: batch/v1beta1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: ecr-credentials-sync
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
suspend: false
|
||||||
|
schedule: 0 */6 * * *
|
||||||
|
failedJobsHistoryLimit: 1
|
||||||
|
successfulJobsHistoryLimit: 1
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
serviceAccountName: ecr-credentials-sync
|
||||||
|
restartPolicy: Never
|
||||||
|
volumes:
|
||||||
|
- name: token
|
||||||
|
emptyDir:
|
||||||
|
medium: Memory
|
||||||
|
initContainers:
|
||||||
|
- image: amazon/aws-cli
|
||||||
|
name: get-token
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
# You will need to set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables if not using
|
||||||
|
# IRSA. It is recommended to store the values in a Secret and load them in the container using envFrom.
|
||||||
|
# envFrom:
|
||||||
|
# - secretRef:
|
||||||
|
# name: aws-credentials
|
||||||
|
env:
|
||||||
|
- name: REGION
|
||||||
|
value: us-east-1 # change this if ECR repo is in a different region
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /token
|
||||||
|
name: token
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ce
|
||||||
|
- aws ecr get-login-password --region ${REGION} > /token/ecr-token
|
||||||
|
containers:
|
||||||
|
- image: bitnami/kubectl
|
||||||
|
name: create-secret
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
env:
|
||||||
|
- name: SECRET_NAME
|
||||||
|
value: <secret name> # this is the generated Secret name
|
||||||
|
- name:
|
||||||
|
value: <account id>.dkr.ecr.<region>.amazonaws.com # fill in the account id and region
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /token
|
||||||
|
name: token
|
||||||
|
command:
|
||||||
|
- /bin/bash
|
||||||
|
- -ce
|
||||||
|
- |-
|
||||||
|
kubectl delete secret --ignore-not-found $SECRET_NAME
|
||||||
|
kubectl create secret docker-registry $SECRET_NAME \
|
||||||
|
--docker-server="$ECR_REGISTRY" \
|
||||||
|
--docker-username=AWS \
|
||||||
|
--docker-password="$(</token/ecr-token)"
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! hint "Using IAM Roles for Service Accounts (IRSA)"
|
||||||
|
If using IRSA, make sure the role attached to the service account has
|
||||||
|
readonly access to ECR. The AWS managed policy
|
||||||
|
`arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly` can be attached
|
||||||
|
to the role.
|
||||||
|
|
||||||
|
Since the cronjob will not create a job right away, after applying the manifest,
|
||||||
|
you can manually create an init job using the following command:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ kubectl create job --from=cronjob/ecr-credentials-sync -n flux-system ecr-credentials-sync-init
|
||||||
|
```
|
||||||
|
|
||||||
|
## GCP Container Registry
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Azure Container Registry
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -118,6 +118,12 @@ flux bootstrap github \
|
|||||||
--personal
|
--personal
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! hint "Deploy Key"
|
||||||
|
The bootstrap command creates a ssh key which it stores as a secret in the
|
||||||
|
Kubernetes cluster. The key is also used to create a deploy key in the GitHub
|
||||||
|
repository. The new deploy key will be linked to the personal access token used
|
||||||
|
to authenticate. Removing the personal access token will remove the deploy key.
|
||||||
|
|
||||||
Run the bootstrap for a repository owned by a GitHub organization:
|
Run the bootstrap for a repository owned by a GitHub organization:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -84,20 +84,19 @@ Depending on what you want to do, some of the following bits might be your first
|
|||||||
- And if you are completely new to Flux v2 and the GitOps Toolkit, take a look at our [Get Started guide](get-started/index.md) and give us feedback
|
- And if you are completely new to Flux v2 and the GitOps Toolkit, take a look at our [Get Started guide](get-started/index.md) and give us feedback
|
||||||
- Check out [how to contribute](contributing/index.md) to the project
|
- Check out [how to contribute](contributing/index.md) to the project
|
||||||
|
|
||||||
### Featured Talks
|
### Upcoming Events
|
||||||
|
- 11 Jan 2021 - [Helm + GitOps = ⚡️⚡️⚡️ with Scott Rigby](https://www.meetup.com/GitOps-Community/events/275348736/)
|
||||||
|
|
||||||
|
### Featured Talks
|
||||||
|
- 14 Dec 2020 - [The Power of GitOps with Flux and Flagger (GitOps Hands-On) with Leigh Capili](https://youtu.be/cB7iXeNLteE)
|
||||||
|
- 30 Nov 2020 - [The Power of GItOps with Flux 2 - Part 3 with Leigh Capili](https://youtu.be/N_K5g7o9JKg)
|
||||||
- 24 Nov 2020 - [Flux CD v2 with GitOps Toolkit - Kubernetes Deployment and Sync Mechanism](https://youtu.be/R6OeIgb7lUI)
|
- 24 Nov 2020 - [Flux CD v2 with GitOps Toolkit - Kubernetes Deployment and Sync Mechanism](https://youtu.be/R6OeIgb7lUI)
|
||||||
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 2 with Leigh Capili](https://youtu.be/fC2YCxQRUwU)
|
- 02 Nov 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 2 with Leigh Capili](https://youtu.be/fC2YCxQRUwU)
|
||||||
- 28 Oct 2020 - [The Kubelist Podcast: Flux with Michael Bridgen](https://www.heavybit.com/library/podcasts/the-kubelist-podcast/ep-5-flux-with-michael-bridgen-of-weaveworks/)
|
- 28 Oct 2020 - [The Kubelist Podcast: Flux with Michael Bridgen](https://www.heavybit.com/library/podcasts/the-kubelist-podcast/ep-5-flux-with-michael-bridgen-of-weaveworks/)
|
||||||
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 1 with Leigh Capili](https://youtu.be/0v5bjysXTL8)
|
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 1 with Leigh Capili](https://youtu.be/0v5bjysXTL8)
|
||||||
- 12 Oct 2020 - [Rawkode Live: Introduction to GitOps Toolkit with Stefan Prodan](https://youtu.be/HqTzuOBP0eY)
|
- 12 Oct 2020 - [Rawkode Live: Introduction to GitOps Toolkit with Stefan Prodan](https://youtu.be/HqTzuOBP0eY)
|
||||||
- 4 Sep 2020 - [KubeCon Europe: The road to Flux v2 and Progressive Delivery with Stefan Prodan & Hidde Beydals](https://youtu.be/8v94nUkXsxU)
|
- 04 Sep 2020 - [KubeCon Europe: The road to Flux v2 and Progressive Delivery with Stefan Prodan & Hidde Beydals](https://youtu.be/8v94nUkXsxU)
|
||||||
- 25 June 2020 - [Cloud Native Nordics: Introduction to GitOps & GitOps Toolkit with Alexis Richardson & Stefan Prodan](https://youtu.be/qQBtSkgl7tI)
|
- 25 June 2020 - [Cloud Native Nordics: Introduction to GitOps & GitOps Toolkit with Alexis Richardson & Stefan Prodan](https://youtu.be/qQBtSkgl7tI)
|
||||||
- 7 May 2020 - [GitOps Days - Community Special: GitOps Toolkit Experimentation with Stefan Prodan](https://youtu.be/WHzxunv4DKk?t=6521)
|
- 07 May 2020 - [GitOps Days - Community Special: GitOps Toolkit Experimentation with Stefan Prodan](https://youtu.be/WHzxunv4DKk?t=6521)
|
||||||
|
|
||||||
### Upcoming Events
|
We look forward to seeing you with us!
|
||||||
|
|
||||||
- 12-13 Nov 2020 - [GitOps Days EMEA](https://www.gitopsdays.com/) with talks and workshops on migrating to Flux v2 and Helm Controller
|
|
||||||
- 19 Nov 2020 - [KubeCon NA: Progressive Delivery Techniques with Flagger and Flux v2 with Stefan Prodan](https://kccncna20.sched.com/event/1b04f8408b49976b843a5d0019cb8112)
|
|
||||||
|
|
||||||
We are looking forward to seeing you with us!
|
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ Tasks
|
|||||||
|
|
||||||
### Flux image update feature parity
|
### Flux image update feature parity
|
||||||
|
|
||||||
[= 70% "70%"]
|
[= 80% "80%"]
|
||||||
|
|
||||||
Image automation is available as a prerelease. See [the
|
Image automation is available as a prerelease. See [this
|
||||||
README](https://github.com/fluxcd/image-automation-controller#readme)
|
guide](https://toolkit.fluxcd.io/guides/image-update/) for how to
|
||||||
for instructions on installing it.
|
install and use it.
|
||||||
|
|
||||||
Goals
|
Goals
|
||||||
|
|
||||||
@@ -73,7 +73,8 @@ Tasks
|
|||||||
- [ ] Azure-specific support [fluxcd/image-reflector-controller#11](https://github.com/fluxcd/image-reflector-controller/issues/11)
|
- [ ] Azure-specific support [fluxcd/image-reflector-controller#11](https://github.com/fluxcd/image-reflector-controller/issues/11)
|
||||||
- [x] <span style="color:grey">Design the automation component</span>
|
- [x] <span style="color:grey">Design the automation component</span>
|
||||||
- [x] <span style="color:grey">Implement the image scan/patch/push workflow</span>
|
- [x] <span style="color:grey">Implement the image scan/patch/push workflow</span>
|
||||||
- [ ] Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)
|
- [x] <span style="color:grey">Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)</span>
|
||||||
|
- [x] <span style="color:grey">Write a guide for how to use image automation ([guide here](https://toolkit.fluxcd.io/guides/image-update/))</span>
|
||||||
- [ ] Write a migration guide from Flux annotations
|
- [ ] Write a migration guide from Flux annotations
|
||||||
|
|
||||||
## The road to Helm Operator v2
|
## The road to Helm Operator v2
|
||||||
|
|||||||
6
go.mod
6
go.mod
@@ -6,16 +6,16 @@ require (
|
|||||||
github.com/blang/semver/v4 v4.0.0
|
github.com/blang/semver/v4 v4.0.0
|
||||||
github.com/cyphar/filepath-securejoin v0.2.2
|
github.com/cyphar/filepath-securejoin v0.2.2
|
||||||
github.com/fluxcd/helm-controller/api v0.4.4
|
github.com/fluxcd/helm-controller/api v0.4.4
|
||||||
github.com/fluxcd/image-automation-controller/api v0.1.0
|
github.com/fluxcd/image-automation-controller/api v0.2.0
|
||||||
github.com/fluxcd/image-reflector-controller/api v0.1.0
|
github.com/fluxcd/image-reflector-controller/api v0.1.0
|
||||||
github.com/fluxcd/kustomize-controller/api v0.5.2
|
github.com/fluxcd/kustomize-controller/api v0.5.3
|
||||||
github.com/fluxcd/notification-controller/api v0.5.0
|
github.com/fluxcd/notification-controller/api v0.5.0
|
||||||
github.com/fluxcd/pkg/apis/meta v0.5.0
|
github.com/fluxcd/pkg/apis/meta v0.5.0
|
||||||
github.com/fluxcd/pkg/git v0.1.0
|
github.com/fluxcd/pkg/git v0.1.0
|
||||||
github.com/fluxcd/pkg/runtime v0.4.0
|
github.com/fluxcd/pkg/runtime v0.4.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/source-controller/api v0.5.5
|
github.com/fluxcd/source-controller/api v0.5.6
|
||||||
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
|
||||||
github.com/olekukonko/tablewriter v0.0.4
|
github.com/olekukonko/tablewriter v0.0.4
|
||||||
|
|||||||
12
go.sum
12
go.sum
@@ -177,12 +177,12 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
|
|||||||
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/helm-controller/api v0.4.4 h1:WYf7KokS3ALeE1F2SrviMHtEBGfznP7DkxXwo5pP7f8=
|
github.com/fluxcd/helm-controller/api v0.4.4 h1:WYf7KokS3ALeE1F2SrviMHtEBGfznP7DkxXwo5pP7f8=
|
||||||
github.com/fluxcd/helm-controller/api v0.4.4/go.mod h1:H3fHkKJWcxPz38L1kxBX/MGm5v9XKzeoKZWNM7+dW2o=
|
github.com/fluxcd/helm-controller/api v0.4.4/go.mod h1:H3fHkKJWcxPz38L1kxBX/MGm5v9XKzeoKZWNM7+dW2o=
|
||||||
github.com/fluxcd/image-automation-controller/api v0.1.0 h1:XN/BbhCRoISEb828rfMt2fNe+3s4Zwc+BwhRi3K1SHA=
|
github.com/fluxcd/image-automation-controller/api v0.2.0 h1:1diY89HhpbseqENkd9DLgqsDnkTGZmVDjX5mucNOMr8=
|
||||||
github.com/fluxcd/image-automation-controller/api v0.1.0/go.mod h1:DHjFNvA+kJlSm7cbTaG+Z5smVjMjLw7xzlJc9brP0zY=
|
github.com/fluxcd/image-automation-controller/api v0.2.0/go.mod h1:DHjFNvA+kJlSm7cbTaG+Z5smVjMjLw7xzlJc9brP0zY=
|
||||||
github.com/fluxcd/image-reflector-controller/api v0.1.0 h1:wlqwCy4sZMbbdrgSY9Fd0mfy55kk7dS4Z+icrDlkmmg=
|
github.com/fluxcd/image-reflector-controller/api v0.1.0 h1:wlqwCy4sZMbbdrgSY9Fd0mfy55kk7dS4Z+icrDlkmmg=
|
||||||
github.com/fluxcd/image-reflector-controller/api v0.1.0/go.mod h1:u7vnULekPHXAZgJ35lqCjV2MaJVN0xbD+qt9X9TVCMs=
|
github.com/fluxcd/image-reflector-controller/api v0.1.0/go.mod h1:u7vnULekPHXAZgJ35lqCjV2MaJVN0xbD+qt9X9TVCMs=
|
||||||
github.com/fluxcd/kustomize-controller/api v0.5.2 h1:RHLhDW2q4JOV1ZJhiLYAWpYwVhKVCK74qCrKcJcr5hs=
|
github.com/fluxcd/kustomize-controller/api v0.5.3 h1:zZiWFBQkNytLffOOJJttGFQk7BIUHpT2yoOCG4nyqII=
|
||||||
github.com/fluxcd/kustomize-controller/api v0.5.2/go.mod h1:8Z52j63kRf+NjtVmiJFvI8xLje3ncFTs/uMxcrEJPIA=
|
github.com/fluxcd/kustomize-controller/api v0.5.3/go.mod h1:8Z52j63kRf+NjtVmiJFvI8xLje3ncFTs/uMxcrEJPIA=
|
||||||
github.com/fluxcd/notification-controller/api v0.5.0 h1:xKKFnPVsYl2+GEjgKz5a5Mq6vmy+H2q9d2lJ2jmWJZs=
|
github.com/fluxcd/notification-controller/api v0.5.0 h1:xKKFnPVsYl2+GEjgKz5a5Mq6vmy+H2q9d2lJ2jmWJZs=
|
||||||
github.com/fluxcd/notification-controller/api v0.5.0/go.mod h1:yLd+nrCJUThSkt4U+LLv8TRxqZdR11+gE1S2/bhgqmE=
|
github.com/fluxcd/notification-controller/api v0.5.0/go.mod h1:yLd+nrCJUThSkt4U+LLv8TRxqZdR11+gE1S2/bhgqmE=
|
||||||
github.com/fluxcd/pkg/apis/meta v0.5.0 h1:FaU++mQY0g4sVVl+hG+vk0CXBLbb4EVfRuzs3IjLXvo=
|
github.com/fluxcd/pkg/apis/meta v0.5.0 h1:FaU++mQY0g4sVVl+hG+vk0CXBLbb4EVfRuzs3IjLXvo=
|
||||||
@@ -195,8 +195,8 @@ 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/source-controller/api v0.5.5 h1:F6xmaKSks8YaETG8IEocpJQ1g07JbaJiVJAqmM2jP0M=
|
github.com/fluxcd/source-controller/api v0.5.6 h1:Nj7WebOP8nTTA/yDPwszyjzW5oYI5tVhS/8XWOT+2wk=
|
||||||
github.com/fluxcd/source-controller/api v0.5.5/go.mod h1:/mpW0EM2dUnRey6rffqsSmgNkSAYm+zq9i0GfmTO7I0=
|
github.com/fluxcd/source-controller/api v0.5.6/go.mod h1:/mpW0EM2dUnRey6rffqsSmgNkSAYm+zq9i0GfmTO7I0=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||||
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=
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -34,6 +35,7 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"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/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
@@ -134,7 +136,7 @@ func ExecTemplate(obj interface{}, tmpl, filename string) error {
|
|||||||
return file.Sync()
|
return file.Sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
func KubeClient(kubeConfigPath string, kubeContext string) (client.Client, error) {
|
func KubeConfig(kubeConfigPath string, kubeContext string) (*rest.Config, error) {
|
||||||
configFiles := SplitKubeConfigPath(kubeConfigPath)
|
configFiles := SplitKubeConfigPath(kubeConfigPath)
|
||||||
configOverrides := clientcmd.ConfigOverrides{}
|
configOverrides := clientcmd.ConfigOverrides{}
|
||||||
|
|
||||||
@@ -147,6 +149,15 @@ func KubeClient(kubeConfigPath string, kubeContext string) (client.Client, error
|
|||||||
&configOverrides,
|
&configOverrides,
|
||||||
).ClientConfig()
|
).ClientConfig()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("kubernetes configuration load failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func KubeClient(kubeConfigPath string, kubeContext string) (client.Client, error) {
|
||||||
|
cfg, err := KubeConfig(kubeConfigPath, kubeContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("kubernetes client initialization failed: %w", err)
|
return nil, fmt.Errorf("kubernetes client initialization failed: %w", err)
|
||||||
}
|
}
|
||||||
@@ -370,3 +381,15 @@ func PrintTable(writer io.Writer, header []string, rows [][]string) {
|
|||||||
table.AppendBulk(rows)
|
table.AppendBulk(rows)
|
||||||
table.Render()
|
table.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateComponents(components []string) error {
|
||||||
|
defaults := install.MakeDefaultOptions()
|
||||||
|
bootstrapAllComponents := append(defaults.Components, defaults.ComponentsExtra...)
|
||||||
|
for _, component := range components {
|
||||||
|
if !ContainsItemString(bootstrapAllComponents, component) {
|
||||||
|
return fmt.Errorf("component %s is not available", component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -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/archive/v0.1.0.zip//image-automation-controller-0.1.0/config/crd
|
- https://github.com/fluxcd/image-automation-controller/archive/v0.2.0.zip//image-automation-controller-0.2.0/config/crd
|
||||||
- https://github.com/fluxcd/image-automation-controller/archive/v0.1.0.zip//image-automation-controller-0.1.0/config/manager
|
- https://github.com/fluxcd/image-automation-controller/archive/v0.2.0.zip//image-automation-controller-0.2.0/config/manager
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
group: apps
|
group: apps
|
||||||
|
|||||||
@@ -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/archive/v0.5.2.zip//kustomize-controller-0.5.2/config/crd
|
- https://github.com/fluxcd/kustomize-controller/archive/v0.5.3.zip//kustomize-controller-0.5.3/config/crd
|
||||||
- https://github.com/fluxcd/kustomize-controller/archive/v0.5.2.zip//kustomize-controller-0.5.2/config/manager
|
- https://github.com/fluxcd/kustomize-controller/archive/v0.5.3.zip//kustomize-controller-0.5.3/config/manager
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
group: apps
|
group: apps
|
||||||
|
|||||||
@@ -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/archive/v0.5.5.zip//source-controller-0.5.5/config/crd
|
- https://github.com/fluxcd/source-controller/archive/v0.5.6.zip//source-controller-0.5.6/config/crd
|
||||||
- https://github.com/fluxcd/source-controller/archive/v0.5.5.zip//source-controller-0.5.5/config/manager
|
- https://github.com/fluxcd/source-controller/archive/v0.5.6.zip//source-controller-0.5.6/config/manager
|
||||||
patchesJson6902:
|
patchesJson6902:
|
||||||
- target:
|
- target:
|
||||||
group: apps
|
group: apps
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ markdown_extensions:
|
|||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Introduction: index.md
|
- Introduction: index.md
|
||||||
|
- Core Concepts: core-concepts/index.md
|
||||||
- Get Started: get-started/index.md
|
- Get Started: get-started/index.md
|
||||||
- Guides:
|
- Guides:
|
||||||
- Installation: guides/installation.md
|
- Installation: guides/installation.md
|
||||||
@@ -100,6 +101,7 @@ nav:
|
|||||||
- Create tenant: cmd/flux_create_tenant.md
|
- Create tenant: cmd/flux_create_tenant.md
|
||||||
- Create secret: cmd/flux_create_secret.md
|
- Create secret: cmd/flux_create_secret.md
|
||||||
- Create secret git: cmd/flux_create_secret_git.md
|
- Create secret git: cmd/flux_create_secret_git.md
|
||||||
|
- Create secret helm: cmd/flux_create_secret_helm.md
|
||||||
- Delete: cmd/flux_delete.md
|
- Delete: cmd/flux_delete.md
|
||||||
- Delete kustomization: cmd/flux_delete_kustomization.md
|
- Delete kustomization: cmd/flux_delete_kustomization.md
|
||||||
- Delete helmrelease: cmd/flux_delete_helmrelease.md
|
- Delete helmrelease: cmd/flux_delete_helmrelease.md
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type Options struct {
|
|||||||
Version string
|
Version string
|
||||||
Namespace string
|
Namespace string
|
||||||
Components []string
|
Components []string
|
||||||
|
ComponentsExtra []string
|
||||||
EventsAddr string
|
EventsAddr string
|
||||||
Registry string
|
Registry string
|
||||||
ImagePullSecret string
|
ImagePullSecret string
|
||||||
@@ -42,6 +43,7 @@ func MakeDefaultOptions() Options {
|
|||||||
Version: "latest",
|
Version: "latest",
|
||||||
Namespace: "flux-system",
|
Namespace: "flux-system",
|
||||||
Components: []string{"source-controller", "kustomize-controller", "helm-controller", "notification-controller"},
|
Components: []string{"source-controller", "kustomize-controller", "helm-controller", "notification-controller"},
|
||||||
|
ComponentsExtra: []string{"image-reflector-controller", "image-automation-controller"},
|
||||||
EventsAddr: "",
|
EventsAddr: "",
|
||||||
Registry: "ghcr.io/fluxcd",
|
Registry: "ghcr.io/fluxcd",
|
||||||
ImagePullSecret: "",
|
ImagePullSecret: "",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package sync
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &manifestgen.Manifest{
|
return &manifestgen.Manifest{
|
||||||
Path: filepath.Join(options.TargetPath, options.Namespace, options.ManifestFile),
|
Path: path.Join(options.TargetPath, options.Namespace, options.ManifestFile),
|
||||||
Content: fmt.Sprintf("---\n%s---\n%s", resourceToString(gitData), resourceToString(ksData)),
|
Content: fmt.Sprintf("---\n%s---\n%s", resourceToString(gitData), resourceToString(ksData)),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user