From b1f91affb1356c473d1839f924ad1fa77b65b72f Mon Sep 17 00:00:00 2001 From: Benjamin Ash Date: Tue, 23 Apr 2019 11:00:19 -0400 Subject: [PATCH 01/30] chart: add support for deploying a global Git configuration. --- chart/flux/templates/deployment.yaml | 11 +++++++++++ chart/flux/templates/gitconfig.yaml | 15 +++++++++++++++ .../flux/templates/helm-operator-deployment.yaml | 11 +++++++++++ chart/flux/values.yaml | 5 +++++ 4 files changed, 42 insertions(+) create mode 100644 chart/flux/templates/gitconfig.yaml diff --git a/chart/flux/templates/deployment.yaml b/chart/flux/templates/deployment.yaml index 5243fc9cb..52af68423 100644 --- a/chart/flux/templates/deployment.yaml +++ b/chart/flux/templates/deployment.yaml @@ -41,6 +41,11 @@ spec: name: {{ template "flux.fullname" . }}-ssh-config defaultMode: 0600 {{- end }} + {{- if .Values.git.config }} + - name: gitconfig + configMap: + name: {{ template "flux.fullname" . }}-gitconfig + {{- end }} - name: git-key secret: {{- if .Values.git.secretName }} @@ -95,6 +100,12 @@ spec: mountPath: /root/.ssh readOnly: true {{- end }} + {{- if .Values.git.config }} + - name: gitconfig + mountPath: /root/.gitconfig + subPath: .gitconfig + readOnly: true + {{- end }} - name: git-key mountPath: /etc/fluxd/ssh readOnly: true diff --git a/chart/flux/templates/gitconfig.yaml b/chart/flux/templates/gitconfig.yaml new file mode 100644 index 000000000..7ab9a106b --- /dev/null +++ b/chart/flux/templates/gitconfig.yaml @@ -0,0 +1,15 @@ +{{- if .Values.git.config -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "flux.fullname" . }}-gitconfig +data: + .gitconfig: | + {{- if contains "\n" .Values.git.config }} + {{- range $value := .Values.git.config | splitList "\n" }} + {{ print $value }} + {{- end }} + {{- else }} + {{ .Values.git.config }} + {{- end }} +{{- end -}} diff --git a/chart/flux/templates/helm-operator-deployment.yaml b/chart/flux/templates/helm-operator-deployment.yaml index 168b1ca30..207391ad4 100644 --- a/chart/flux/templates/helm-operator-deployment.yaml +++ b/chart/flux/templates/helm-operator-deployment.yaml @@ -41,6 +41,11 @@ spec: name: {{ template "flux.fullname" . }}-ssh-config defaultMode: 0600 {{- end }} + {{- if .Values.git.config }} + - name: gitconfig + configMap: + name: {{ template "flux.fullname" . }}-gitconfig + {{- end }} - name: git-key secret: {{- if .Values.helmOperator.git.secretName }} @@ -84,6 +89,12 @@ spec: subPath: known_hosts readOnly: true {{- end }} + {{- if .Values.git.config }} + - name: gitconfig + mountPath: /root/.gitconfig + subPath: .gitconfig + readOnly: true + {{- end }} - name: git-key mountPath: /etc/fluxd/ssh readOnly: true diff --git a/chart/flux/values.yaml b/chart/flux/values.yaml index 2ad33c907..f33de8ddd 100644 --- a/chart/flux/values.yaml +++ b/chart/flux/values.yaml @@ -137,6 +137,11 @@ git: # add ./identity.pub as a deployment key with write access in your Git repo # set the secret name (flux-ssh) below secretName: "" + # Global Git configuration See https://git-scm.com/docs/git-config for more details. + config: "" + # config: | + # [credential "https://github.com"] + # username = foo registry: # Period at which to check for updated images From f6b982d25575a353d8de2f52a01ff6983ef5fe52 Mon Sep 17 00:00:00 2001 From: Benjamin Ash Date: Wed, 24 Apr 2019 20:56:37 -0400 Subject: [PATCH 02/30] chart: move gitconfig to secrets - update docs - add tests --- chart/flux/README.md | 3 ++ chart/flux/templates/_helpers.tpl | 13 +++++++++ chart/flux/templates/deployment.yaml | 15 +++++----- chart/flux/templates/gitconfig.yaml | 16 ++++------- .../templates/helm-operator-deployment.yaml | 15 +++++----- chart/flux/values.yaml | 11 +++++--- test/e2e/e2e-flux-chart.sh | 28 ++++++++++++++++++- test/e2e/gitconfig | 2 ++ 8 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 test/e2e/gitconfig diff --git a/chart/flux/README.md b/chart/flux/README.md index bc8df514a..ad8a68189 100755 --- a/chart/flux/README.md +++ b/chart/flux/README.md @@ -213,6 +213,9 @@ The following tables lists the configurable parameters of the Weave Flux chart a | `git.pollInterval` | `5m` | Period at which to poll git repo for new commits | `git.timeout` | `20s` | Duration after which git operations time out | `git.secretName` | `None` | Kubernetes secret with the SSH private key. Superceded by `helmOperator.git.secretName` if set. +| `git.config.enabled` | `false` | Mount `$HOME/.gitconfig` via Secret into the Flux and HelmOperator Pods, allowing for custom global Git configuration +| `git.config.secretName` | `Computed` | Kubernetes secret with the global Git configuration +| `git.config.data` | `None` | Global Git configuration per [git-config](https://git-scm.com/docs/git-config) | `gpgKeys.secretName` | `None` | Kubernetes secret with GPG keys the Flux daemon should import | `ssh.known_hosts` | `None` | The contents of an SSH `known_hosts` file, if you need to supply host key(s) | `registry.pollInterval` | `5m` | Period at which to check for updated images diff --git a/chart/flux/templates/_helpers.tpl b/chart/flux/templates/_helpers.tpl index 3b575696e..24f4a36c8 100644 --- a/chart/flux/templates/_helpers.tpl +++ b/chart/flux/templates/_helpers.tpl @@ -60,3 +60,16 @@ repositories: username: "{{ .username | default "" }}" {{- end }} {{- end -}} + +{{/* +Create the name of the Git config Secret. +*/}} +{{- define "git.config.secretName" -}} +{{- if .Values.git.config.enabled }} + {{- if .Values.git.config.secretName -}} + {{ default "default" .Values.git.config.secretName }} + {{- else -}} + {{ default (printf "%s-git-config" (include "flux.fullname" .)) }} +{{- end -}} +{{- end }} +{{- end }} diff --git a/chart/flux/templates/deployment.yaml b/chart/flux/templates/deployment.yaml index 52af68423..cbcb59054 100644 --- a/chart/flux/templates/deployment.yaml +++ b/chart/flux/templates/deployment.yaml @@ -41,10 +41,11 @@ spec: name: {{ template "flux.fullname" . }}-ssh-config defaultMode: 0600 {{- end }} - {{- if .Values.git.config }} - - name: gitconfig - configMap: - name: {{ template "flux.fullname" . }}-gitconfig + {{- if .Values.git.config.enabled }} + - name: git-config + secret: + secretName: {{ include "git.config.secretName" . }} + defaultMode: 0400 {{- end }} - name: git-key secret: @@ -100,10 +101,10 @@ spec: mountPath: /root/.ssh readOnly: true {{- end }} - {{- if .Values.git.config }} - - name: gitconfig + {{- if .Values.git.config.enabled }} + - name: git-config mountPath: /root/.gitconfig - subPath: .gitconfig + subPath: gitconfig readOnly: true {{- end }} - name: git-key diff --git a/chart/flux/templates/gitconfig.yaml b/chart/flux/templates/gitconfig.yaml index 7ab9a106b..a08bd2211 100644 --- a/chart/flux/templates/gitconfig.yaml +++ b/chart/flux/templates/gitconfig.yaml @@ -1,15 +1,9 @@ -{{- if .Values.git.config -}} +{{- if .Values.git.config.enabled -}} apiVersion: v1 -kind: ConfigMap +kind: Secret metadata: - name: {{ template "flux.fullname" . }}-gitconfig + name: {{ include "git.config.secretName" . }} +type: Opaque data: - .gitconfig: | - {{- if contains "\n" .Values.git.config }} - {{- range $value := .Values.git.config | splitList "\n" }} - {{ print $value }} - {{- end }} - {{- else }} - {{ .Values.git.config }} - {{- end }} + gitconfig: {{ .Values.git.config.data | b64enc }} {{- end -}} diff --git a/chart/flux/templates/helm-operator-deployment.yaml b/chart/flux/templates/helm-operator-deployment.yaml index 207391ad4..5b75a503d 100644 --- a/chart/flux/templates/helm-operator-deployment.yaml +++ b/chart/flux/templates/helm-operator-deployment.yaml @@ -41,10 +41,11 @@ spec: name: {{ template "flux.fullname" . }}-ssh-config defaultMode: 0600 {{- end }} - {{- if .Values.git.config }} - - name: gitconfig - configMap: - name: {{ template "flux.fullname" . }}-gitconfig + {{- if .Values.git.config.enabled }} + - name: git-config + secret: + secretName: {{ include "git.config.secretName" . }} + defaultMode: 0400 {{- end }} - name: git-key secret: @@ -89,10 +90,10 @@ spec: subPath: known_hosts readOnly: true {{- end }} - {{- if .Values.git.config }} - - name: gitconfig + {{- if .Values.git.config.enabled }} + - name: git-config mountPath: /root/.gitconfig - subPath: .gitconfig + subPath: gitconfig readOnly: true {{- end }} - name: git-key diff --git a/chart/flux/values.yaml b/chart/flux/values.yaml index f33de8ddd..bd15ed53d 100644 --- a/chart/flux/values.yaml +++ b/chart/flux/values.yaml @@ -138,10 +138,13 @@ git: # set the secret name (flux-ssh) below secretName: "" # Global Git configuration See https://git-scm.com/docs/git-config for more details. - config: "" - # config: | - # [credential "https://github.com"] - # username = foo + config: + enabled: false + secretName: "" + data: "" + # data: | + # [credential "https://github.com"] + # username = foo registry: # Period at which to check for updated images diff --git a/test/e2e/e2e-flux-chart.sh b/test/e2e/e2e-flux-chart.sh index c23fa2e47..42713e340 100755 --- a/test/e2e/e2e-flux-chart.sh +++ b/test/e2e/e2e-flux-chart.sh @@ -5,6 +5,7 @@ set -o errexit export KUBECONFIG="$(kind get kubeconfig-path --name="kind")" REPO_ROOT=$(git rev-parse --show-toplevel) KNOWN_HOSTS=$(cat ${REPO_ROOT}/test/e2e/known_hosts) +GITCONFIG=$(cat ${REPO_ROOT}/test/e2e/gitconfig) echo ">>> Loading $(docker/image-tag) into the cluster" kind load docker-image "docker.io/weaveworks/flux:$(docker/image-tag)" @@ -17,6 +18,9 @@ helm install --name flux --wait \ --set git.url=ssh://git@gitsrv/git-server/repos/cluster.git \ --set git.secretName=ssh-git \ --set git.pollInterval=30s \ +--set git.config.secretName=gitconfig \ +--set git.config.enabled=true \ +--set-string git.config.data="${GITCONFIG}" \ --set helmOperator.tag=$(docker/image-tag) \ --set helmOperator.create=true \ --set helmOperator.createCRD=true \ @@ -25,10 +29,32 @@ helm install --name flux --wait \ --set-string ssh.known_hosts="${KNOWN_HOSTS}" \ ${REPO_ROOT}/chart/flux -echo '>>> Waiting for namespace demo' +echo '>>> Waiting for gitconfig secret' retries=12 count=0 ok=false +until ${ok}; do + actual=$(kubectl get secrets -n flux gitconfig -ojsonpath={..data.gitconfig} | base64 -d) + if [ "${actual}" == "${GITCONFIG}" ]; then + echo -e "Expected Git configuration deployed\n" + kubectl get secrets -n flux gitconfig && echo + ok=true + else + ok=false + sleep 10 + fi + count=$(($count + 1)) + if [[ ${count} -eq ${retries} ]]; then + kubectl -n flux get secrets + echo "No more retries left" + exit 1 + fi +done + +echo '>>> Waiting for namespace demo' +retries=12 +count=1 +ok=false until ${ok}; do kubectl describe ns/demo && ok=true || ok=false sleep 10 diff --git a/test/e2e/gitconfig b/test/e2e/gitconfig new file mode 100644 index 000000000..5998e1a79 --- /dev/null +++ b/test/e2e/gitconfig @@ -0,0 +1,2 @@ +[core] + editor = vim From 690b60d4004a2870c9070bf7e258da5a03f115c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20R=C3=BCegg?= Date: Thu, 25 Apr 2019 08:53:21 +0200 Subject: [PATCH 03/30] Add production users of Flux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Simon Rüegg --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e624807c8..e84d723eb 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Its major features are: ### Who is using Flux in production +- [APPUiO](https://appuio.ch) - [Control Plane](https://control-plane.io) - [Crowd Riff](https://crowdriff.com) - [College of William & Mary](https://www.wm.edu) @@ -67,7 +68,8 @@ Its major features are: - [Qordoba](https://qordoba.com) - [Troii](https://troii.com/) - [Under Armour](https://www.underarmour.com) -- [Weave Cloud](https://cloud.weave.works) +- [VSHN](https://vshn.ch) +- [Weave Cloud](https://cloud.weave.works) If you too are using Flux in production; please submit a PR to add your organization to the list! From f24437f1760689f91fb0c5ee9b756525a7716ea6 Mon Sep 17 00:00:00 2001 From: Daniel Holbach Date: Thu, 25 Apr 2019 09:53:43 +0100 Subject: [PATCH 04/30] Add feature request issue template Signed-off-by: Daniel Holbach --- .github/ISSUE_TEMPLATE/feature_request.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..d41b9c0b0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,22 @@ +--- +name: Feature request +about: Suggest a new feature for Weave Flux +title: '' +labels: [blocked-needs-validation, enhancement] +assignees: '' + +--- + +**Describe the feature** +A clear and concise description of the feature. + +**What would the new user story look like?** +How would the new interaction with Flux look like? +0. What are the prerequisites for this? +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expect to happen. From cc14641689b1384fa717264301d9a3054240dbd4 Mon Sep 17 00:00:00 2001 From: Daniel Holbach Date: Thu, 25 Apr 2019 09:56:37 +0100 Subject: [PATCH 05/30] add diagram suggestion --- .github/ISSUE_TEMPLATE/feature_request.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index d41b9c0b0..403bae073 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -18,5 +18,7 @@ How would the new interaction with Flux look like? 3. Scroll down to '....' 4. See error +Feel free to add a diagram if that helps explaining things. + **Expected behavior** A clear and concise description of what you expect to happen. From 74e2744a88f9b147078d364c012e8ec0393e61ce Mon Sep 17 00:00:00 2001 From: Daniel Holbach Date: Thu, 25 Apr 2019 10:04:32 +0100 Subject: [PATCH 06/30] update feature request boilerplate text --- .github/ISSUE_TEMPLATE/feature_request.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 403bae073..e6d76287e 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -11,12 +11,11 @@ assignees: '' A clear and concise description of the feature. **What would the new user story look like?** -How would the new interaction with Flux look like? +How would the new interaction with Flux look like? E.g. 0. What are the prerequisites for this? -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error +1. User starts up Flux using the --add-frobnication flag +2. New commits in git branch happen +3. Deployments happen, which include frobnication Feel free to add a diagram if that helps explaining things. From 9089637efd09a8e27c8d22e78a7d701de37266dd Mon Sep 17 00:00:00 2001 From: Chris Denneen Date: Thu, 25 Apr 2019 12:28:08 -0400 Subject: [PATCH 07/30] Update annotation document Fixes #1982 to remove deprecated -c (--controller) flag from examples. --- site/annotations-tutorial.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/annotations-tutorial.md b/site/annotations-tutorial.md index 4fd2c0eaf..34a100475 100644 --- a/site/annotations-tutorial.md +++ b/site/annotations-tutorial.md @@ -144,13 +144,13 @@ Notice that `podinfo` is on `v1.3.2` and in state `automated`. To check which images are avaible for podinfo run ```sh -fluxctl list-images -c demo:deployment/podinfo +fluxctl list-images -w demo:deployment/podinfo ``` Now let's change the policy for `podinfo` to target `1.4.*` releases: ```sh -fluxctl policy -c demo:deployment/podinfo --tag-all='1.4.*' +fluxctl policy -w demo:deployment/podinfo --tag-all='1.4.*' ``` On the command-line you should see a message just like this one: @@ -197,7 +197,7 @@ fluxctl sync To check which image is current, run ```sh -fluxctl list-images -c demo:deployment/podinfo +fluxctl list-images -w demo:deployment/podinfo ``` In our case this is `1.4.2` (it could be a later image too). Let's say an @@ -207,7 +207,7 @@ That's easy. Rollback to `1.4.1`: ```sh -fluxctl release -c demo:deployment/podinfo -i stefanprodan/podinfo:1.4.1 +fluxctl release --workload demo:deployment/podinfo -i stefanprodan/podinfo:1.4.1 ``` The response should be @@ -239,7 +239,7 @@ and the diff for this is going to look like this: Lock to `1.4.1` with a message describing why: ```sh -fluxctl lock -c demo:deployment/podinfo -m "1.4.2 does not work for us" +fluxctl lock -w demo:deployment/podinfo -m "1.4.2 does not work for us" ``` The resulting diff should look like this @@ -271,4 +271,4 @@ kubectl logs -n default deploy/flux -f If you should have any questions, find us on Slack in the [#flux channel](https://weave-community.slack.com/messages/flux/), get -an invite to it [here](https://slack.weave.works/). \ No newline at end of file +an invite to it [here](https://slack.weave.works/). From b9274f383f7e35f6b739a647894c66d99f7b2c58 Mon Sep 17 00:00:00 2001 From: Chris Denneen Date: Thu, 25 Apr 2019 12:44:08 -0400 Subject: [PATCH 08/30] Fix workspace to workload typo Fixes #1986 --- cmd/fluxctl/release_cmd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/fluxctl/release_cmd.go b/cmd/fluxctl/release_cmd.go index ced1d0b01..05b565b59 100644 --- a/cmd/fluxctl/release_cmd.go +++ b/cmd/fluxctl/release_cmd.go @@ -67,7 +67,7 @@ func (opts *workloadReleaseOpts) Command() *cobra.Command { // Deprecated cmd.Flags().StringSliceVarP(&opts.controllers, "controller", "c", []string{}, "List of controllers to release :/") - cmd.Flags().MarkDeprecated("controller", "changed to --workspace, use that instead") + cmd.Flags().MarkDeprecated("controller", "changed to --workload, use that instead") return cmd } From f79982dced4c4ce24ed9b8a47ca4c44ad8e0c858 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Mon, 29 Apr 2019 17:56:39 +0300 Subject: [PATCH 09/30] Bump Flux version to 1.12.1 --- chart/flux/Chart.yaml | 4 ++-- chart/flux/values.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chart/flux/Chart.yaml b/chart/flux/Chart.yaml index d5355294d..d7ccab927 100644 --- a/chart/flux/Chart.yaml +++ b/chart/flux/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v1 -appVersion: "1.12.0" -version: 0.9.1 +appVersion: "1.12.1" +version: 0.9.2 kubeVersion: ">=1.9.0-0" name: flux description: Flux is a tool that automatically ensures that the state of a cluster matches what is specified in version control diff --git a/chart/flux/values.yaml b/chart/flux/values.yaml index bd15ed53d..550b19de3 100644 --- a/chart/flux/values.yaml +++ b/chart/flux/values.yaml @@ -7,7 +7,7 @@ replicaCount: 1 image: repository: docker.io/weaveworks/flux - tag: 1.12.0 + tag: 1.12.1 pullPolicy: IfNotPresent pullSecret: From b7e323dc48e9479ef6fb6776c5a5311a4afac4b5 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Mon, 29 Apr 2019 17:59:00 +0300 Subject: [PATCH 10/30] Update change log --- chart/flux/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/chart/flux/CHANGELOG.md b/chart/flux/CHANGELOG.md index 9e613b752..22247eaee 100644 --- a/chart/flux/CHANGELOG.md +++ b/chart/flux/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.9.1 (2019-04-29) + +### Improvements + + - Updated Flux to `1.12.1` + [weaveworks/flux#1993](https://github.com/weaveworks/flux/pull/1993) + ## 0.9.1 (2019-04-17) ### Improvements From 74da91ce76dc67a7348a9c7d1e793261cb743ec1 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 29 Apr 2019 22:02:20 +0200 Subject: [PATCH 11/30] Fix error shadowing when parsing manifests This caused parsing errors in YAML files to go unnoticed (the files where simply not included in the result) --- cluster/kubernetes/resource/load.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cluster/kubernetes/resource/load.go b/cluster/kubernetes/resource/load.go index e5352783f..109b63600 100644 --- a/cluster/kubernetes/resource/load.go +++ b/cluster/kubernetes/resource/load.go @@ -140,7 +140,7 @@ func ParseMultidoc(multidoc []byte, source string) (map[string]KubeManifest, err // NOTE: gopkg.in/yaml.v3 supports round tripping comments // by using `gopkg.in/yaml.v3.Node`. var val interface{} - if err := decoder.Decode(&val); err != nil { + if err = decoder.Decode(&val); err != nil { break } bytes, err := yaml.Marshal(val) From ba650c05fbdc48e41a0ca50a3e6fe84ac2d17080 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Mon, 29 Apr 2019 22:14:01 +0200 Subject: [PATCH 12/30] Add test --- cluster/kubernetes/resource/load_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cluster/kubernetes/resource/load_test.go b/cluster/kubernetes/resource/load_test.go index 0ea8facfa..ffffbe79f 100644 --- a/cluster/kubernetes/resource/load_test.go +++ b/cluster/kubernetes/resource/load_test.go @@ -142,6 +142,18 @@ metadata: assert.Len(t, resources, 1) } +func TestParseError(t *testing.T) { + doc := `--- +kind: ConfigMap +metadata: + name: bigmap # contains a tab at the beginning +` + buffer := bytes.NewBufferString(doc) + + _, err := ParseMultidoc(buffer.Bytes(), "test") + assert.Error(t, err) +} + func TestParseCronJob(t *testing.T) { doc := `--- apiVersion: batch/v1beta1 From 3c1b3532eaac0cb447b3875f5e1cb657d7cf312e Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 30 Apr 2019 10:33:22 +0200 Subject: [PATCH 13/30] Typo: 'workspace' -> 'workload' Co-Authored-By: Chris Denneen --- cmd/fluxctl/automate_cmd.go | 2 +- cmd/fluxctl/deautomate_cmd.go | 2 +- cmd/fluxctl/list_images_cmd.go | 2 +- cmd/fluxctl/lock_cmd.go | 2 +- cmd/fluxctl/policy_cmd.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/fluxctl/automate_cmd.go b/cmd/fluxctl/automate_cmd.go index e93b13c59..c53b28592 100644 --- a/cmd/fluxctl/automate_cmd.go +++ b/cmd/fluxctl/automate_cmd.go @@ -37,7 +37,7 @@ func (opts *workloadAutomateOpts) Command() *cobra.Command { // Deprecated cmd.Flags().StringVarP(&opts.controller, "controller", "c", "", "Controller to automate") - cmd.Flags().MarkDeprecated("controller", "changed to --workspace, use that instead") + cmd.Flags().MarkDeprecated("controller", "changed to --workload, use that instead") return cmd } diff --git a/cmd/fluxctl/deautomate_cmd.go b/cmd/fluxctl/deautomate_cmd.go index ae11a7565..c006ffdbd 100644 --- a/cmd/fluxctl/deautomate_cmd.go +++ b/cmd/fluxctl/deautomate_cmd.go @@ -37,7 +37,7 @@ func (opts *workloadDeautomateOpts) Command() *cobra.Command { // Deprecated cmd.Flags().StringVarP(&opts.controller, "controller", "c", "", "Controller to deautomate") - cmd.Flags().MarkDeprecated("controller", "changed to --workspace, use that instead") + cmd.Flags().MarkDeprecated("controller", "changed to --workload, use that instead") return cmd } diff --git a/cmd/fluxctl/list_images_cmd.go b/cmd/fluxctl/list_images_cmd.go index d960d3a65..416bab759 100644 --- a/cmd/fluxctl/list_images_cmd.go +++ b/cmd/fluxctl/list_images_cmd.go @@ -42,7 +42,7 @@ func (opts *imageListOpts) Command() *cobra.Command { // Deprecated cmd.Flags().StringVarP(&opts.controller, "controller", "c", "", "Show images for this controller") - cmd.Flags().MarkDeprecated("controller", "changed to --workspace, use that instead") + cmd.Flags().MarkDeprecated("controller", "changed to --workload, use that instead") return cmd } diff --git a/cmd/fluxctl/lock_cmd.go b/cmd/fluxctl/lock_cmd.go index 4c88c0495..d968e4026 100644 --- a/cmd/fluxctl/lock_cmd.go +++ b/cmd/fluxctl/lock_cmd.go @@ -37,7 +37,7 @@ func (opts *workloadLockOpts) Command() *cobra.Command { // Deprecated cmd.Flags().StringVarP(&opts.workload, "controller", "c", "", "Controller to lock") - cmd.Flags().MarkDeprecated("controller", "changed to --workspace, use that instead") + cmd.Flags().MarkDeprecated("controller", "changed to --workload, use that instead") return cmd } diff --git a/cmd/fluxctl/policy_cmd.go b/cmd/fluxctl/policy_cmd.go index 65ddec55a..ba871186b 100644 --- a/cmd/fluxctl/policy_cmd.go +++ b/cmd/fluxctl/policy_cmd.go @@ -70,7 +70,7 @@ containers which aren't explicitly named. // Deprecated flags.StringVarP(&opts.controller, "controller", "c", "", "Controller to modify") - flags.MarkDeprecated("controller", "changed to --workspace, use that instead") + flags.MarkDeprecated("controller", "changed to --workload, use that instead") return cmd } From 97b46dec514190a6a940d726e1e482b1d8cba449 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 30 Apr 2019 10:15:19 +0200 Subject: [PATCH 14/30] Update MAINTAINERS and include email addresses --- MAINTAINERS | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 67ae5dd2a..e20bb9d01 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4,7 +4,9 @@ at https://slack.weave.works/). In alphabetical order: -Hidde Beydals (github: @hiddeco, slack: hidde) -Justin Barrick (github: @justinbarrick, slack: Justin Barrick) -Michael Bridgen (github: @squaremo, slack: mbridgen) -Nick Cabatoff (github: @ncabatoff, slack: Nick Cabatoff) +Alfonso Acosta, Weaveworks (github: @2opremio, slack: fons) +Hidde Beydals, Weaveworks (github: @hiddeco, slack: hidde) +Justin Barrick, independent (github: @justinbarrick, slack: Justin Barrick) +Michael Bridgen, Weaveworks (github: @squaremo, slack: mbridgen) +Nick Cabatoff, independent (github: @ncabatoff, slack: Nick Cabatoff) +Stefan Prodan, Weaveworks (github: @stefanprodan, slack: stefan) From b5ceec619bb11fbcefca52faa2c8f2200cc04bac Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Tue, 30 Apr 2019 13:27:27 +0300 Subject: [PATCH 15/30] Add reinstall helm release to docs --- site/helm-integration.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/site/helm-integration.md b/site/helm-integration.md index 97eb4d138..596a98d81 100644 --- a/site/helm-integration.md +++ b/site/helm-integration.md @@ -7,6 +7,7 @@ menu_order: 90 * [The `HelmRelease` custom resource](#the-helmrelease-custom-resource) + [Using a chart from a Git repo instead of a Helm repo](#using-a-chart-from-a-git-repo-instead-of-a-helm-repo) - [Notifying Helm Operator about Git changes](#notifying-helm-operator-about-git-changes) + + [Reinstalling a Helm release](#reinstalling-a-helm-release) + [What the Helm Operator does](#what-the-helm-operator-does) * [Supplying values to the chart](#supplying-values-to-the-chart) + [`.spec.values`](#specvalues) @@ -119,6 +120,20 @@ OK > either need to port forward before making the request or put something > in front of it to serve as a gatekeeper. +#### Reinstalling a Helm release + +If a Helm release upgrade fails due to incompatible changes like modifying +an immutable field (e.g. headless svc to ClusterIP) +you can reinstall it using the following command: + +```sh +$ kubectl delete hr/my-release +``` + +When the Helm Operator receives a delete event from Kubernetes API it will +call Tiller and purge the Helm release. On the next Flux sync, the Helm Release +object will be created and the Helm Operator will install it. + ### What the Helm Operator does When the Helm Operator sees a `HelmRelease` resource in the From a0950b43925f6b69fae5103db747603f063e5543 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 30 Apr 2019 14:04:21 +0300 Subject: [PATCH 16/30] Change title size Co-Authored-By: stefanprodan --- site/helm-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/helm-integration.md b/site/helm-integration.md index 596a98d81..6a3b35239 100644 --- a/site/helm-integration.md +++ b/site/helm-integration.md @@ -120,7 +120,7 @@ OK > either need to port forward before making the request or put something > in front of it to serve as a gatekeeper. -#### Reinstalling a Helm release +### Reinstalling a Helm release If a Helm release upgrade fails due to incompatible changes like modifying an immutable field (e.g. headless svc to ClusterIP) From 3b3a3d623ca66c66b6f31eade562d65b3a2ea6ea Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Tue, 30 Apr 2019 13:27:27 +0300 Subject: [PATCH 17/30] Add reinstall helm release to docs --- site/helm-integration.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/site/helm-integration.md b/site/helm-integration.md index 97eb4d138..596a98d81 100644 --- a/site/helm-integration.md +++ b/site/helm-integration.md @@ -7,6 +7,7 @@ menu_order: 90 * [The `HelmRelease` custom resource](#the-helmrelease-custom-resource) + [Using a chart from a Git repo instead of a Helm repo](#using-a-chart-from-a-git-repo-instead-of-a-helm-repo) - [Notifying Helm Operator about Git changes](#notifying-helm-operator-about-git-changes) + + [Reinstalling a Helm release](#reinstalling-a-helm-release) + [What the Helm Operator does](#what-the-helm-operator-does) * [Supplying values to the chart](#supplying-values-to-the-chart) + [`.spec.values`](#specvalues) @@ -119,6 +120,20 @@ OK > either need to port forward before making the request or put something > in front of it to serve as a gatekeeper. +#### Reinstalling a Helm release + +If a Helm release upgrade fails due to incompatible changes like modifying +an immutable field (e.g. headless svc to ClusterIP) +you can reinstall it using the following command: + +```sh +$ kubectl delete hr/my-release +``` + +When the Helm Operator receives a delete event from Kubernetes API it will +call Tiller and purge the Helm release. On the next Flux sync, the Helm Release +object will be created and the Helm Operator will install it. + ### What the Helm Operator does When the Helm Operator sees a `HelmRelease` resource in the From b984a1fb3e3997dc4c7a8334af7c5893b6d22c86 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 30 Apr 2019 14:04:21 +0300 Subject: [PATCH 18/30] Change title size Co-Authored-By: stefanprodan --- site/helm-integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/helm-integration.md b/site/helm-integration.md index 596a98d81..6a3b35239 100644 --- a/site/helm-integration.md +++ b/site/helm-integration.md @@ -120,7 +120,7 @@ OK > either need to port forward before making the request or put something > in front of it to serve as a gatekeeper. -#### Reinstalling a Helm release +### Reinstalling a Helm release If a Helm release upgrade fails due to incompatible changes like modifying an immutable field (e.g. headless svc to ClusterIP) From 4c0ce35b698ba04f9a2c1ca74d74fe06580cb421 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 30 Apr 2019 20:24:47 +0200 Subject: [PATCH 19/30] Improve internal kubernetes error logging 1. Remove duplicated timestamp keyval 2. Print full path to kubernetes file emitting the error --- cmd/fluxd/main.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/fluxd/main.go b/cmd/fluxd/main.go index 8ea9098b8..999601d39 100644 --- a/cmd/fluxd/main.go +++ b/cmd/fluxd/main.go @@ -8,6 +8,7 @@ import ( "os" "os/exec" "os/signal" + "runtime" "strconv" "strings" "sync" @@ -194,8 +195,11 @@ func main() { // Silence access errors logged internally by client-go k8slog := log.With(logger, "type", "internal kubernetes error", - "ts", log.DefaultTimestampUTC, - "caller", log.Caller(5)) // we want to log one level deeper than k8sruntime.HandleError + "kubernetes_caller", log.Valuer(func() interface{} { + _, file, line, _ := runtime.Caller(5) // we want to log one level deeper than k8sruntime.HandleError + idx := strings.Index(file, "/vendor/") + return file[idx+1:] + ":" + strconv.Itoa(line) + })) logErrorUnlessAccessRelated := func(err error) { errLower := strings.ToLower(err.Error()) if k8serrors.IsForbidden(err) || k8serrors.IsNotFound(err) || From 32e9df59cf4ee10e05836f9bce5bc13021a69ebc Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 30 Apr 2019 21:12:01 +0200 Subject: [PATCH 20/30] Improve fluxctl connection error It now looks like: ``` $ fluxctl Error: No pod found in namespace "default" using the following selectors: app=flux name in (flux,fluxd,weave-flux-agent) Make sure Flux is running in namespace "default". If Flux is running in another namespace, please supply it to --k8s-fwd-ns= Run 'fluxctl identity --help' for usage. ``` --- cmd/fluxctl/portforward.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/fluxctl/portforward.go b/cmd/fluxctl/portforward.go index ddf2786c9..272cf9bfd 100644 --- a/cmd/fluxctl/portforward.go +++ b/cmd/fluxctl/portforward.go @@ -13,7 +13,7 @@ import ( // Attempt to create PortForwards to fluxes that match the label selectors until a Flux // is found or an error is returned. func tryPortforwards(ns string, selectors ...metav1.LabelSelector) (p *portforward.PortForward, err error) { - message := fmt.Sprintf("Flux pod not found for labels in namespace %s:", ns) + message := fmt.Sprintf("No pod found in namespace %q using the following selectors:", ns) for _, selector := range selectors { p, err = tryPortforward(ns, selector) @@ -27,7 +27,8 @@ func tryPortforwards(ns string, selectors ...metav1.LabelSelector) (p *portforwa message = fmt.Sprintf("%s\n %s", message, metav1.FormatLabelSelector(&selector)) } } - + message = fmt.Sprintf("%s\n\nMake sure Flux is running in namespace %q.\n"+ + "If Flux is running in another different namespace, please supply it to --k8s-fwd-ns.", message, ns) if err != nil { err = errors.New(message) } From 5aa9827c730587c43a4623a4cc75192a3ca1789d Mon Sep 17 00:00:00 2001 From: Semyon Slepov Date: Wed, 1 May 2019 12:50:27 +0100 Subject: [PATCH 21/30] Allow to enable garbage collection in Helm chart --- chart/flux/README.md | 1 + chart/flux/templates/deployment.yaml | 3 +++ chart/flux/values.yaml | 3 +++ 3 files changed, 7 insertions(+) diff --git a/chart/flux/README.md b/chart/flux/README.md index ad8a68189..aa6467435 100755 --- a/chart/flux/README.md +++ b/chart/flux/README.md @@ -276,6 +276,7 @@ The following tables lists the configurable parameters of the Weave Flux chart a | `helmOperator.affinity` | `{}` | Affinity properties for the helmOperator deployment | `kube.config` | [See values.yaml](/chart/flux/values.yaml#L151-L165) | Override for kubectl default config in the Flux pod(s). | `prometheus.enabled` | `false` | If enabled, adds prometheus annotations to Flux and helmOperator pod(s) +| `syncGarbageCollection.enabled` | `false` | If enabled, fluxd will delete resources that it created, but are no longer present in git (experimental, see [garbage collection](/site/garbagecollection.md)) Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example: diff --git a/chart/flux/templates/deployment.yaml b/chart/flux/templates/deployment.yaml index cbcb59054..b08e77803 100644 --- a/chart/flux/templates/deployment.yaml +++ b/chart/flux/templates/deployment.yaml @@ -191,6 +191,9 @@ spec: - --connect=wss://cloud.weave.works/api/flux - --token={{ .Values.token }} {{- end }} + {{- if .Values.syncGarbageCollection.enabled }} + - --sync-garbage-collection={{ .Values.syncGarbageCollection.enabled }} + {{- end }} {{- if .Values.additionalArgs }} {{ toYaml .Values.additionalArgs | indent 10 }} {{- end }} diff --git a/chart/flux/values.yaml b/chart/flux/values.yaml index 550b19de3..98176db87 100644 --- a/chart/flux/values.yaml +++ b/chart/flux/values.yaml @@ -229,6 +229,9 @@ extraEnvs: [] prometheus: enabled: false +syncGarbageCollection: + enabled: false + # Add your own init container or uncomment and modify the given example. initContainers: {} # flux-init: # <- will be used as container name From 5bb7826a8eb1943007896b38d53bd4f86569d8c5 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Wed, 1 May 2019 16:44:07 +0200 Subject: [PATCH 22/30] Fetch HelmRelease before applying status updates Due to the status of the HelmRelease being updated in two different processes, we sometimes got a "the object has been modified; please apply your changes to the latest version and try again" message back from the API. Fetching a fresh copy of the resource and applying the updates on top of that minimizes the chance this happens. --- integrations/helm/chartsync/chartsync.go | 32 ++++++++++++------------ integrations/helm/status/conditions.go | 18 +++++++------ integrations/helm/status/status.go | 20 +++++++++------ 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/integrations/helm/chartsync/chartsync.go b/integrations/helm/chartsync/chartsync.go index 681f578d5..6b353b61f 100644 --- a/integrations/helm/chartsync/chartsync.go +++ b/integrations/helm/chartsync/chartsync.go @@ -175,7 +175,7 @@ func (chs *ChartChangeSync) Run(stopCh <-chan struct{}, errc chan error, wg *syn // Then why .. did you say .. it had changed? It may have been removed. Add it back and let it signal again. chs.logger.Log("warning", "mirrored git repo disappeared after signalling change", "repo", mirror) for _, fhr := range resources { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, "git mirror missing; starting mirroring again") + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, "git mirror missing; starting mirroring again") chs.maybeMirror(fhr) } continue @@ -187,7 +187,7 @@ func (chs *ChartChangeSync) Run(stopCh <-chan struct{}, errc chan error, wg *syn chs.logger.Log("info", "repo not ready yet, while attempting chart sync", "repo", mirror, "status", string(status)) for _, fhr := range resources { // TODO(michael) log if there's a problem with the following? - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, err.Error()) } continue } @@ -204,7 +204,7 @@ func (chs *ChartChangeSync) Run(stopCh <-chan struct{}, errc chan error, wg *syn refHead, err := repo.Revision(ctx, ref) cancel() if err != nil { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonGitNotReady, "problem cloning from local git mirror: "+err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonGitNotReady, "problem cloning from local git mirror: "+err.Error()) chs.logger.Log("warning", "could not get revision for ref while checking for changes", "resource", fhr.ResourceID().String(), "repo", mirror, "ref", ref, "err", err) continue } @@ -220,7 +220,7 @@ func (chs *ChartChangeSync) Run(stopCh <-chan struct{}, errc chan error, wg *syn commits, err := repo.CommitsBetween(ctx, cloneForChart.head, refHead, path) cancel() if err != nil { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonGitNotReady, "problem cloning from local git mirror: "+err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonGitNotReady, "problem cloning from local git mirror: "+err.Error()) chs.logger.Log("warning", "could not get revision for ref while checking for changes", "resource", fhr.ResourceID().String(), "repo", mirror, "ref", ref, "err", err) continue } @@ -232,7 +232,7 @@ func (chs *ChartChangeSync) Run(stopCh <-chan struct{}, errc chan error, wg *syn newClone, err := repo.Export(ctx, refHead) cancel() if err != nil { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonGitNotReady, "problem cloning from local git mirror: "+err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonGitNotReady, "problem cloning from local git mirror: "+err.Error()) chs.logger.Log("warning", "could not clone from mirror while checking for changes", "resource", fhr.ResourceID().String(), "repo", mirror, "ref", ref, "err", err) continue } @@ -331,24 +331,24 @@ func (chs *ChartChangeSync) reconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { repo, ok := chs.mirrors.Get(mirrorName(chartSource)) if !ok { chs.maybeMirror(fhr) - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, "git repo "+chartSource.GitURL+" not mirrored yet") + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, "git repo "+chartSource.GitURL+" not mirrored yet") chs.logger.Log("info", "chart repo not cloned yet", "resource", fhr.ResourceID().String()) } else { status, err := repo.Status() if status != git.RepoReady { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, "git repo not mirrored yet: "+err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionUnknown, ReasonGitNotReady, "git repo not mirrored yet: "+err.Error()) chs.logger.Log("info", "chart repo not ready yet", "resource", fhr.ResourceID().String(), "status", string(status), "err", err) } } return } - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionTrue, ReasonCloned, "successfully cloned git repo") + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionTrue, ReasonCloned, "successfully cloned git repo") chartPath = filepath.Join(chartClone.export.Dir(), chartSource.Path) chartRevision = chartClone.head if chs.config.UpdateDeps && !fhr.Spec.ChartSource.GitChartSource.SkipDepUpdate { if err := updateDependencies(chartPath, ""); err != nil { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonDependencyFailed, err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonDependencyFailed, err.Error()) chs.logger.Log("warning", "failed to update chart dependencies", "resource", fhr.ResourceID().String(), "err", err) return } @@ -357,11 +357,11 @@ func (chs *ChartChangeSync) reconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { chartSource := fhr.Spec.ChartSource.RepoChartSource path, err := ensureChartFetched(chs.config.ChartCache, chartSource) if err != nil { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonDownloadFailed, "chart download failed: "+err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionFalse, ReasonDownloadFailed, "chart download failed: "+err.Error()) chs.logger.Log("info", "chart download failed", "resource", fhr.ResourceID().String(), "err", err) return } - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionTrue, ReasonDownloaded, "chart fetched: "+filepath.Base(path)) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionTrue, ReasonDownloaded, "chart fetched: "+filepath.Base(path)) chartPath = path chartRevision = chartSource.Version } @@ -369,11 +369,11 @@ func (chs *ChartChangeSync) reconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { if rel == nil { _, err := chs.release.Install(chartPath, releaseName, fhr, release.InstallAction, opts, &chs.kubeClient) if err != nil { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonInstallFailed, err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonInstallFailed, err.Error()) chs.logger.Log("warning", "failed to install chart", "resource", fhr.ResourceID().String(), "err", err) return } - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionTrue, ReasonSuccess, "helm install succeeded") + chs.setCondition(fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionTrue, ReasonSuccess, "helm install succeeded") if err = status.UpdateReleaseRevision(chs.ifClient.FluxV1beta1().HelmReleases(fhr.Namespace), fhr, chartRevision); err != nil { chs.logger.Log("warning", "could not update the release revision", "namespace", fhr.Namespace, "resource", fhr.Name, "err", err) } @@ -397,11 +397,11 @@ func (chs *ChartChangeSync) reconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { } _, err = chs.release.Install(chartPath, releaseName, fhr, release.UpgradeAction, opts, &chs.kubeClient) if err != nil { - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonUpgradeFailed, err.Error()) + chs.setCondition(fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonUpgradeFailed, err.Error()) chs.logger.Log("warning", "failed to upgrade chart", "resource", fhr.ResourceID().String(), "err", err) return } - chs.setCondition(&fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionTrue, ReasonSuccess, "helm upgrade succeeded") + chs.setCondition(fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionTrue, ReasonSuccess, "helm upgrade succeeded") if err = status.UpdateReleaseRevision(chs.ifClient.FluxV1beta1().HelmReleases(fhr.Namespace), fhr, chartRevision); err != nil { chs.logger.Log("warning", "could not update the release revision", "resource", fhr.ResourceID().String(), "err", err) } @@ -463,7 +463,7 @@ func (chs *ChartChangeSync) getCustomResourcesForMirror(mirror string) ([]fluxv1 // information. New information is something that adds or changes the // status, reason or message (i.e., anything but the transition time) // for one of the types of condition. -func (chs *ChartChangeSync) setCondition(fhr *fluxv1beta1.HelmRelease, typ fluxv1beta1.HelmReleaseConditionType, st v1.ConditionStatus, reason, message string) error { +func (chs *ChartChangeSync) setCondition(fhr fluxv1beta1.HelmRelease, typ fluxv1beta1.HelmReleaseConditionType, st v1.ConditionStatus, reason, message string) error { for _, c := range fhr.Status.Conditions { if c.Type == typ && c.Status == st && c.Message == message && c.Reason == reason { return nil diff --git a/integrations/helm/status/conditions.go b/integrations/helm/status/conditions.go index 6715675ed..14e892aa5 100644 --- a/integrations/helm/status/conditions.go +++ b/integrations/helm/status/conditions.go @@ -3,6 +3,7 @@ package status import ( "github.com/weaveworks/flux/integrations/apis/flux.weave.works/v1beta1" v1beta1client "github.com/weaveworks/flux/integrations/client/clientset/versioned/typed/flux.weave.works/v1beta1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // We can't rely on having UpdateStatus, or strategic merge patching @@ -27,13 +28,16 @@ updates: status.Conditions = newConditions } -// UpdateConditions applies the updates to the HelmRelease given, and -// updates the resource in the cluster. -func UpdateConditions(client v1beta1client.HelmReleaseInterface, fhr *v1beta1.HelmRelease, updates ...v1beta1.HelmReleaseCondition) error { - fhrCopy := fhr.DeepCopy() - - UpdateConditionsPatch(&fhrCopy.Status, updates...) - _, err := client.UpdateStatus(fhrCopy) +// UpdateConditions retrieves a new copy of the HelmRelease given, +// applies the updates to this copy, and updates the resource in the +// cluster. +func UpdateConditions(client v1beta1client.HelmReleaseInterface, fhr v1beta1.HelmRelease, updates ...v1beta1.HelmReleaseCondition) error { + cFhr, err := client.Get(fhr.Name, v1.GetOptions{}) + if err != nil { + return err + } + UpdateConditionsPatch(&cFhr.Status, updates...) + _, err = client.UpdateStatus(cFhr) return err } diff --git a/integrations/helm/status/status.go b/integrations/helm/status/status.go index d21a49b08..96ca621fb 100644 --- a/integrations/helm/status/status.go +++ b/integrations/helm/status/status.go @@ -102,18 +102,24 @@ bail: } func UpdateReleaseStatus(client v1beta1client.HelmReleaseInterface, fhr v1beta1.HelmRelease, releaseName, releaseStatus string) error { - fhr.Status.ReleaseName = releaseName - fhr.Status.ReleaseStatus = releaseStatus - - _, err := client.UpdateStatus(&fhr) + cFhr, err := client.Get(fhr.Name, metav1.GetOptions{}) + if err != nil { + return err + } + cFhr.Status.ReleaseName = releaseName + cFhr.Status.ReleaseStatus = releaseStatus + _, err = client.UpdateStatus(cFhr) return err } func UpdateReleaseRevision(client v1beta1client.HelmReleaseInterface, fhr v1beta1.HelmRelease, revision string) error { - fhr.Status.Revision = revision - - _, err := client.UpdateStatus(&fhr) + cFhr, err := client.Get(fhr.Name, metav1.GetOptions{}) + if err != nil { + return err + } + cFhr.Status.Revision = revision + _, err = client.UpdateStatus(cFhr) return err } From 6635ca806ad40e37dd6d6613c1b4d92d8171ae88 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Wed, 1 May 2019 17:44:42 +0200 Subject: [PATCH 23/30] Detect and ignore HelmRelease status update As the update function receives any update, and we do not want to run expensive dry-runs for status updates, but do want them for resyncs. Theoretically this should not result in resyncs being skipped, as a resync will redeliver a resource that was already known, which should equal to oldFhr.Status == newFhr.Status. --- integrations/helm/operator/operator.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/integrations/helm/operator/operator.go b/integrations/helm/operator/operator.go index 30761ab67..9c3c300c3 100644 --- a/integrations/helm/operator/operator.go +++ b/integrations/helm/operator/operator.go @@ -282,8 +282,19 @@ func (c *Controller) enqueueUpdateJob(old, new interface{}) { return } - log := []string{"info", "enqueuing release upgrade"} - if diff := cmp.Diff(oldFhr.Spec, newFhr.Spec); diff != "" && c.logDiffs { + diff := cmp.Diff(oldFhr.Spec, newFhr.Spec) + + // Filter out any update notifications that are due to status + // updates, as the dry-run that determines if we should upgrade + // is expensive, but _without_ filtering out updates that are + // from the periodic refresh, as we still want to detect (and + // undo) mutations to Helm charts. + if sDiff := cmp.Diff(oldFhr.Status, newFhr.Status); diff == "" && sDiff != "" { + return + } + + log := []string{"info", "enqueuing release"} + if diff != "" && c.logDiffs { log = append(log, "diff", diff) } log = append(log, "resource", newFhr.ResourceID().String()) From 9b4dbef67fe74d4da9193861d3317ff270494249 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Thu, 2 May 2019 16:39:47 +0300 Subject: [PATCH 24/30] Add helm tag filters examples --- site/helm-integration.md | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/site/helm-integration.md b/site/helm-integration.md index 6a3b35239..0f64da5ce 100644 --- a/site/helm-integration.md +++ b/site/helm-integration.md @@ -17,7 +17,6 @@ menu_order: 90 * [External sources](#external-sources) * [Chart files](#chart-files) * [Upgrading images in a `HelmRelease` using Flux](#upgrading-images-in-a-helmrelease-using-flux) - + [Using annotations to control updates to HelmRelease resources](#using-annotations-to-control-updates-to-helmrelease-resources) * [Authentication](#authentication) + [Authentication for Helm repos](#authentication-for-helm-repos) - [Azure ACR repositories](#azure-acr-repositories) @@ -293,8 +292,6 @@ values: port: 4040 ``` -### Using annotations to control updates to `HelmRelease` resources - You can use the [same annotations](./fluxctl.md#using-annotations) in the `HelmRelease` as you would for a Deployment or other workload, to control updates and automation. For the purpose of specifying @@ -302,6 +299,43 @@ filters, the container name is either `chart-image` (if at the top level), or the key under which the image is given (e.g., `"subsystem"` from the example above). +Top level image example: + +```yaml +kind: HelmRelease +metadata: + annotations: + flux.weave.works/automated: "true" + flux.weave.works/tag.chart-image: semver:~4.0 +spec: + values: + image: + repository: bitnami/mongodb + tag: 4.0.3 +``` + +Sub-section images example: + +```yaml +kind: HelmRelease +metadata: + annotations: + flux.weave.works/automated: "true" + flux.weave.works/tag.prometheus: semver:~2.3 + flux.weave.works/tag.alertmanager: glob:v0.15.* + flux.weave.works/tag.nats: regex:^0.6.* +spec: + values: + prometheus: + image: prom/prometheus:v2.3.1 + alertmanager: + image: prom/alertmanager:v0.15.0 + nats: + image: + repository: nats-streaming + tag: 0.6.0 +``` + ------------- **Why use URLs to refer to repositories, rather than names?** [^](#cite-why-repo-urls) From 886048da1acdb614cbfa0982a2b13304d23bf371 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Thu, 2 May 2019 17:34:39 +0200 Subject: [PATCH 25/30] Log and return early if release is not upgradable Before this change the operator would follow the installation path if a Helm release was not in a 'DEPLOYED' state, which would fail later on as a release with the name already existed. We now detect what the state of the release is and return (and log) a descriptive error message in case we can not upgrade the release. --- integrations/helm/chartsync/chartsync.go | 12 ++++++---- integrations/helm/release/release.go | 30 +++++++++++++++++++----- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/integrations/helm/chartsync/chartsync.go b/integrations/helm/chartsync/chartsync.go index 6b353b61f..2e2d5eb53 100644 --- a/integrations/helm/chartsync/chartsync.go +++ b/integrations/helm/chartsync/chartsync.go @@ -293,11 +293,13 @@ func (chs *ChartChangeSync) ReconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { func (chs *ChartChangeSync) reconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { releaseName := release.GetReleaseName(fhr) - // There's no exact way in the Helm API to test whether a release - // exists or not. Instead, try to fetch it, and treat an error as - // not existing (and possibly fail further below, if it meant - // something else). - rel, _ := chs.release.GetDeployedRelease(releaseName) + // Attempt to retrieve an upgradable release, in case no release + // or error is returned, install it. + rel, err := chs.release.GetUpgradableRelease(releaseName) + if err != nil { + chs.logger.Log("warning", "unable to proceed with release", "resource", fhr.ResourceID().String(), "release", releaseName, "err", err) + return + } opts := release.InstallOptions{DryRun: false} diff --git a/integrations/helm/release/release.go b/integrations/helm/release/release.go index ef852f87f..2ccb50da3 100644 --- a/integrations/helm/release/release.go +++ b/integrations/helm/release/release.go @@ -8,6 +8,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" "time" "github.com/ghodss/yaml" @@ -45,7 +46,7 @@ type Release struct { } type Releaser interface { - GetDeployedRelease(name string) (*hapi_release.Release, error) + GetUpgradableRelease(name string) (*hapi_release.Release, error) Install(dir string, releaseName string, fhr flux_v1beta1.HelmRelease, action Action, opts InstallOptions) (*hapi_release.Release, error) } @@ -82,16 +83,33 @@ func GetReleaseName(fhr flux_v1beta1.HelmRelease) string { return releaseName } -// GetDeployedRelease returns a release with Deployed status -func (r *Release) GetDeployedRelease(name string) (*hapi_release.Release, error) { +// GetUpgradableRelease returns a release if the current state of it +// allows an upgrade, a descriptive error if it is not allowed, or +// nil if the release does not exist. +func (r *Release) GetUpgradableRelease(name string) (*hapi_release.Release, error) { rls, err := r.HelmClient.ReleaseContent(name) if err != nil { + if strings.Contains(err.Error(), "not found") { + return nil, nil + } return nil, err } - if rls.Release.Info.Status.GetCode() == hapi_release.Status_DEPLOYED { - return rls.GetRelease(), nil + + release := rls.GetRelease() + status := release.GetInfo().GetStatus() + + switch status.GetCode() { + case hapi_release.Status_DEPLOYED: + return release, nil + case hapi_release.Status_FAILED: + return nil, fmt.Errorf("release requires a rollback before it can be upgraded (%s)", status.GetCode().String()) + case hapi_release.Status_PENDING_INSTALL, + hapi_release.Status_PENDING_UPGRADE, + hapi_release.Status_PENDING_ROLLBACK: + return nil, fmt.Errorf("operation pending for release (%s)", status.GetCode().String()) + default: + return nil, fmt.Errorf("current state prevents it from being upgraded (%s)", status.GetCode().String()) } - return nil, nil } func (r *Release) canDelete(name string) (bool, error) { From 5ecc1718c12300e600622b405b48d6aa56745864 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Thu, 2 May 2019 00:36:15 +0200 Subject: [PATCH 26/30] Ignore discovery errors for metrics resources The Metrics API tends to be misconfigured, causing discovery errors which ultimately makes syncs fail. This change makes Flux ignore those errors. --- cluster/kubernetes/sync.go | 5 +++++ cluster/kubernetes/sync_test.go | 34 ++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cluster/kubernetes/sync.go b/cluster/kubernetes/sync.go index b71a37461..e6f7f67a7 100644 --- a/cluster/kubernetes/sync.go +++ b/cluster/kubernetes/sync.go @@ -206,6 +206,11 @@ func (c *Cluster) getAllowedResourcesBySelector(selector string) (map[string]*ku return nil, err } for gv, e := range discErr.Groups { + if strings.HasSuffix(gv.Group, "metrics.k8s.io") { + // The Metrics API tends to be misconfigured, causing errors. + // We just ignore them, since it doesn't make sense to sync metrics anyways. + continue + } // Tolerate empty GroupVersions due to e.g. misconfigured custom metrics if e.Error() != fmt.Sprintf("Got empty response for: %v", gv) { return nil, err diff --git a/cluster/kubernetes/sync_test.go b/cluster/kubernetes/sync_test.go index 12bfc607b..3bd780387 100644 --- a/cluster/kubernetes/sync_test.go +++ b/cluster/kubernetes/sync_test.go @@ -266,7 +266,7 @@ func TestSyncTolerateEmptyGroupVersion(t *testing.T) { // Add a GroupVersion without API Resources fakeClient := kube.client.coreClient.(*corefake.Clientset) - fakeClient.Resources = append(fakeClient.Resources, &metav1.APIResourceList{GroupVersion: "custom.metrics.k8s.io/v1beta1"}) + fakeClient.Resources = append(fakeClient.Resources, &metav1.APIResourceList{GroupVersion: "foo.bar/v1"}) // We should tolerate the error caused in the cache due to the // GroupVersion being empty @@ -278,6 +278,38 @@ func TestSyncTolerateEmptyGroupVersion(t *testing.T) { assert.NoError(t, err) } +type failingDiscoveryClient struct { + discovery.DiscoveryInterface +} + +func (d *failingDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + return nil, errors.NewServiceUnavailable("") +} + +func TestSyncTolerateMetricsErrors(t *testing.T) { + kube, _, cancel := setup(t) + + // Replace the discovery client by one returning errors when asking for resources + cancel() + crdClient := crdfake.NewSimpleClientset() + shutdown := make(chan struct{}) + defer close(shutdown) + newDiscoveryClient := &failingDiscoveryClient{kube.client.coreClient.Discovery()} + kube.client.discoveryClient = MakeCachedDiscovery(newDiscoveryClient, crdClient, shutdown) + + // Check that syncing results in an error for groups other than metrics + fakeClient := kube.client.coreClient.(*corefake.Clientset) + fakeClient.Resources = []*metav1.APIResourceList{{GroupVersion: "foo.bar/v1"}} + err := kube.Sync(cluster.SyncSet{}) + assert.Error(t, err) + + // Check that syncing doesn't result in an error for a metrics group + kube.client.discoveryClient.(*cachedDiscovery).CachedDiscoveryInterface.Invalidate() + fakeClient.Resources = []*metav1.APIResourceList{{GroupVersion: "custom.metrics.k8s.io/v1"}} + err = kube.Sync(cluster.SyncSet{}) + assert.NoError(t, err) +} + func TestSync(t *testing.T) { const ns1 = `--- apiVersion: v1 From 8f588b0318d4ecabdd635dc4e79e7cc42128e05e Mon Sep 17 00:00:00 2001 From: Jeremy Barneron Date: Tue, 7 May 2019 16:18:36 +0100 Subject: [PATCH 27/30] Added babylon partners to flux production orgs --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e84d723eb..ed7cef3a2 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Its major features are: - [Under Armour](https://www.underarmour.com) - [VSHN](https://vshn.ch) - [Weave Cloud](https://cloud.weave.works) +- [Babylon Health](https://www.babylonhealth.com/) If you too are using Flux in production; please submit a PR to add your organization to the list! From 7183f1337abf80ac90b41aafbd94f95502e59637 Mon Sep 17 00:00:00 2001 From: Alfonso Acosta Date: Tue, 7 May 2019 20:37:04 +0200 Subject: [PATCH 28/30] Fix (Flux)HelmRelease cluster lookups The value obtained by `_, value := range slice` is overwritten on every iteration. Thus, saving a pointer to `value` is dangerous since its content will be overwritten in the next iteration. From https://golang.org/ref/spec#For_range : > For each entry it assigns iteration values to corresponding > iteration variables if present and then executes the block. But the iteration variables are the same on each iteration. More explicitly, from [the gccgo source code](https://github.com/golang/gofrontend/blob/e387439bfd24d5e142874b8e68e7039f74c744d7/go/statements.cc#L5593-L5604): ``` // The loop we generate: // len_temp := len(range) // range_temp := range // for index_temp = 0; index_temp < len_temp; index_temp++ { // value_temp = range_temp[index_temp] // index = index_temp // value = value_temp // original body // } ``` --- cluster/kubernetes/resourcekinds.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cluster/kubernetes/resourcekinds.go b/cluster/kubernetes/resourcekinds.go index 6ffb3bd1d..dab1bd207 100644 --- a/cluster/kubernetes/resourcekinds.go +++ b/cluster/kubernetes/resourcekinds.go @@ -397,8 +397,8 @@ func (fhr *fluxHelmReleaseKind) getWorkloads(c *Cluster, namespace string) ([]wo } var workloads []workload - for _, f := range fluxHelmReleases.Items { - workloads = append(workloads, makeFluxHelmReleaseWorkload(&f)) + for i, _ := range fluxHelmReleases.Items { + workloads = append(workloads, makeFluxHelmReleaseWorkload(&fluxHelmReleases.Items[i])) } return workloads, nil @@ -459,8 +459,8 @@ func (hr *helmReleaseKind) getWorkloads(c *Cluster, namespace string) ([]workloa } var workloads []workload - for _, f := range helmReleases.Items { - workloads = append(workloads, makeHelmReleaseWorkload(&f)) + for i, _ := range helmReleases.Items { + workloads = append(workloads, makeHelmReleaseWorkload(&helmReleases.Items[i])) } return workloads, nil From 0dbb1d6c3b2e05c512611f27afecd2db7f19fa3f Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Wed, 8 May 2019 10:44:57 +0200 Subject: [PATCH 29/30] Add changelog entry for Flux v1.12.2 --- CHANGELOG.md | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4af7a08db..259bc5097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,55 @@ This is the changelog for the Flux daemon; the changelog for the Helm operator is in [./CHANGELOG-helmop.md](./CHANGELOG-helmop.md). +## 1.12.2 (2019-05-08) + +This is a patch release. + +### Fixes + +- Fix error shadowing when parsing YAML manifests + [weaveworks/flux#1994][] +- Fix 'workspace' -> 'workload' typo in deprecated controller flag + [weaveworks/flux#1987][] [weaveworks/flux#1996][] +- Improve internal Kubernetes error logging, by removing the duplicate + timestamp and providing a full path to the Kubernetes file emitting + the error + [weaveworks/flux#2000][] +- Improve `fluxctl` auto portforward connection error, by better + guiding the user about what could be wrong + [weaveworks/flux#2001][] +- Ignore discovery errors for metrics resources, to prevent syncs from + failing when the metrics API is misconfigured + [weaveworks/flux#2009][] +- Fix `(Flux)HelmRelease` cluster lookups, before this change, the + same resource ID would be reported for all `HelmRelease`s with e.g. + `fluctl list-workloads` + [weaveworks/flux#2018][] + + +### Maintenance and documentation + +- Replace deprecated `--controller` flag in documentation with + `--workload` + [weaveworks/flux#1985][] +- Update `MAINTAINERS` and include email addresses + [weaveworks/flux#1995][] + +### Thanks + +Thanks to @2opremio, @cdenneen, @hiddeco, @jan-schumacher, @squaremo, +@stefanprodan for contributions. + +[weaveworks/flux#1985]: https://github.com/weaveworks/flux/pull/1985 +[weaveworks/flux#1987]: https://github.com/weaveworks/flux/pull/1987 +[weaveworks/flux#1994]: https://github.com/weaveworks/flux/pull/1994 +[weaveworks/flux#1995]: https://github.com/weaveworks/flux/pull/1995 +[weaveworks/flux#1996]: https://github.com/weaveworks/flux/pull/1996 +[weaveworks/flux#2000]: https://github.com/weaveworks/flux/pull/2000 +[weaveworks/flux#2001]: https://github.com/weaveworks/flux/pull/2001 +[weaveworks/flux#2009]: https://github.com/weaveworks/flux/pull/2009 +[weaveworks/flux#2018]: https://github.com/weaveworks/flux/pull/2018 + ## 1.12.1 (2019-04-25) This is a patch release. @@ -29,7 +78,7 @@ This is a patch release. [weaveworks/flux#1932][] - Move images to DockerHub and have a separate pre-releases image repo [weaveworks/flux#1949][], [weaveworks/flux#1956][] -- Suppoort `arm` and `arm64` builds [weaveworks/flux#1950][] +- Support `arm` and `arm64` builds [weaveworks/flux#1950][] - Refactor the core image metadata fetching func [weaveworks/flux#1935][] - Update client-go to v1.11 [weaveworks/flux#1929][] From b81917dab7e0490da0af3ddb617f4c2f55d0a8b7 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Wed, 8 May 2019 10:46:12 +0200 Subject: [PATCH 30/30] Bump version in example deployment to v1.12.2 --- deploy/flux-deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/flux-deployment.yaml b/deploy/flux-deployment.yaml index c8a6691cf..7bfd7cdbb 100644 --- a/deploy/flux-deployment.yaml +++ b/deploy/flux-deployment.yaml @@ -54,7 +54,7 @@ spec: # There are no ":latest" images for flux. Find the most recent # release or image version at https://hub.docker.com/r/weaveworks/flux/tags # and replace the tag here. - image: docker.io/weaveworks/flux:1.12.1 + image: docker.io/weaveworks/flux:1.12.2 imagePullPolicy: IfNotPresent resources: requests: