diff --git a/CHANGELOG-helmop.md b/CHANGELOG-helmop.md index 7f33dffe6..4264dce97 100644 --- a/CHANGELOG-helmop.md +++ b/CHANGELOG-helmop.md @@ -1,10 +1,17 @@ -## 0.5.4 (TBA) +## 0.6.0 (2019-02-07) ### Improvements - Add option to limit the Helm operator to a single namespace [weaveworks/flux#1664](https://github.com/weaveworks/flux/pull/1664) +### Thanks + +Without the contributions of @brandon-bethke-neudesic, @errordeveloper, +@ncabatoff, @stefanprodan, @squaremo, and feedback of our +[#flux](https://slack.weave.works/) inhabitants this release would not +have been possible -- thanks to all of you! + ## 0.5.3 (2019-01-14) ### Improvements diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b905a9b6..4c699ed6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,32 @@ This is the changelog for the Flux daemon; the changelog for the Helm operator is in [./CHANGELOG-helmop.md](./CHANGELOG-helmop.md). +## 1.10.1 (2019-02-13) + +This release provides a deeper integration with Azure (DevOps Git hosts +and ACR) and allows configuring how `fluxctl` finds `fluxd` (useful for +clusters with multiple fluxd installations). + +### Improvements + +- Support Azure DevOps Git hosts + [weaveworks/flux#1729][#1729] + [weaveworks/flux#1731][#1731] +- Use AKS credentials for ACR + [weaveworks/flux#1694][#1694] +- Make port forward label selector configurable + [weaveworks/flux#1727][#1727] + +### Thanks + +Lots of thanks to @alanjcastonguay, @hiddeco, and @sarath-p for their +contributions to this release. + +[#1694]: https://github.com/weaveworks/flux/pull/1694 +[#1727]: https://github.com/weaveworks/flux/pull/1727 +[#1729]: https://github.com/weaveworks/flux/pull/1729 +[#1731]: https://github.com/weaveworks/flux/pull/1731 + ## 1.10.0 (2019-02-07) This release adds the `--registry-exclude-image` flag for excluding diff --git a/Gopkg.lock b/Gopkg.lock index aa2bbae05..f9696fc42 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -577,12 +577,12 @@ version = "v0.0.1" [[projects]] - digest = "1:8e243c568f36b09031ec18dff5f7d2769dcf5ca4d624ea511c8e3197dc3d352d" + digest = "1:cbaf13cdbfef0e4734ed8a7504f57fe893d471d62a35b982bf6fb3f036449a66" name = "github.com/spf13/pflag" packages = ["."] pruneopts = "" - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" + revision = "298182f68c66c05229eb03ac171abe6e309ee79a" + version = "v1.0.3" [[projects]] digest = "1:a30066593578732a356dc7e5d7f78d69184ca65aeeff5939241a3ab10559bb06" diff --git a/chart/flux/CHANGELOG.md b/chart/flux/CHANGELOG.md index 1c579a7f7..2e7fa7ba7 100644 --- a/chart/flux/CHANGELOG.md +++ b/chart/flux/CHANGELOG.md @@ -1,10 +1,33 @@ -## 0.6.1 (TBA) +## 0.6.2 (2019-02-11) ### Improvements + - Allow chart images to be pulled from a private container registry + [weaveworks/flux#1718](https://github.com/weaveworks/flux/pull/1718) + +### Bug fixes + + - Fix helm-op allow namespace flag mapping + [weaveworks/flux#1724](https://github.com/weaveworks/flux/pull/1724) + +## 0.6.1 (2019-02-07) + +### Improvements + + - Updated Flux to `1.10.0` and Helm operator to `0.6.0` + [weaveworks/flux#1713](https://github.com/weaveworks/flux/pull/1713) + - Add option to exclude container images + [weaveworks/flux#1659](https://github.com/weaveworks/flux/pull/1659) + - Add option to mount custom `repositories.yaml` + [weaveworks/flux#1671](https://github.com/weaveworks/flux/pull/1671) - Add option to limit the Helm operator to a single namespace [weaveworks/flux#1664](https://github.com/weaveworks/flux/pull/1664) +### Bug fixes + + - Fix custom SSH secret mapping + [weaveworks/flux#1710](https://github.com/weaveworks/flux/pull/1710) + ## 0.6.0 (2019-01-14) **Note** To fix the connectivity problems between Flux and memcached we've changed the diff --git a/chart/flux/Chart.yaml b/chart/flux/Chart.yaml index be6b4a353..645f490d9 100644 --- a/chart/flux/Chart.yaml +++ b/chart/flux/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v1 -appVersion: "1.9.0" -version: 0.6.0 +appVersion: "1.10.0" +version: 0.6.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/README.md b/chart/flux/README.md index dddd9c568..81187fb7b 100755 --- a/chart/flux/README.md +++ b/chart/flux/README.md @@ -187,6 +187,7 @@ The following tables lists the configurable parameters of the Weave Flux chart a | `image.tag` | Image tag | `<VERSION>` | `replicaCount` | Number of flux pods to deploy, more than one is not desirable. | `1` | `image.pullPolicy` | Image pull policy | `IfNotPresent` +| `image.pullSecret` | Image pull secret | `None` | `resources.requests.cpu` | CPU resource requests for the flux deployment | `50m` | `resources.requests.memory` | Memory resource requests for the flux deployment | `64Mi` | `resources.limits` | CPU/memory resource limits for the flux deployment | `None` @@ -222,9 +223,13 @@ The following tables lists the configurable parameters of the Weave Flux chart a | `registry.ecr.region` | Restrict ECR scanning to these AWS regions; if empty, only the cluster's region will be scanned | `None` | `registry.ecr.includeId` | Restrict ECR scanning to these AWS account IDs; if empty, all account IDs that aren't excluded may be scanned | `None` | `registry.ecr.excludeId` | Do not scan ECR for images in these AWS account IDs; the default is to exclude the EKS system account | `602401143452` +| `registry.acr.enabled` | Mount `azure.json` via HostPath into the Flux Pod, enabling Flux to use AKS's service principal for ACR authentication | `false` +| `registry.acr.hostPath` | Alternative location of `azure.json` on the host | `/etc/kubernetes/azure.json` | `memcached.verbose` | Enable request logging in memcached | `false` | `memcached.maxItemSize` | Maximum size for one item | `1m` | `memcached.maxMemory` | Maximum memory to use, in megabytes | `64` +| `memcached.pullSecret` | Image pull secret | `None` +| `memcached.repository` | Image repository | `memcached` | `memcached.resources` | CPU/memory resource requests/limits for memcached | `None` | `helmOperator.create` | If `true`, install the Helm operator | `false` | `helmOperator.createCRD` | Create the `v1beta1` and `v1alpha2` flux CRDs. Dependent on `helmOperator.create=true` | `true` @@ -232,6 +237,7 @@ The following tables lists the configurable parameters of the Weave Flux chart a | `helmOperator.tag` | Helm operator image tag | `<VERSION>` | `helmOperator.replicaCount` | Number of helm operator pods to deploy, more than one is not desirable. | `1` | `helmOperator.pullPolicy` | Helm operator image pull policy | `IfNotPresent` +| `helmOperator.pullSecret` | Image pull secret | `None` | `helmOperator.updateChartDeps` | Update dependencies for charts | `true` | `helmOperator.git.pollInterval` | Period at which to poll git repo for new commits | `git.pollInterval` | `helmOperator.git.timeout` | Duration after which git operations time out | `git.timeout` diff --git a/chart/flux/templates/deployment.yaml b/chart/flux/templates/deployment.yaml index 42974e26a..309943781 100644 --- a/chart/flux/templates/deployment.yaml +++ b/chart/flux/templates/deployment.yaml @@ -24,6 +24,10 @@ spec: release: {{ .Release.Name }} spec: serviceAccountName: {{ template "flux.serviceAccountName" . }} + {{- if .Values.image.pullSecret }} + imagePullSecrets: + - name: {{ .Values.image.pullSecret }} + {{- end }} volumes: - name: kubedir configMap: @@ -45,6 +49,12 @@ spec: - name: git-keygen emptyDir: medium: Memory + {{- if .Values.registry.acr.enabled }} + - name: acr-credentials + hostPath: + path: "{{ .Values.registry.acr.hostPath }}" + type: "" + {{- end }} containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" @@ -66,6 +76,11 @@ spec: readOnly: true - name: git-keygen mountPath: /var/fluxd/keygen + {{- if .Values.registry.acr.enabled }} + - name: acr-credentials + mountPath: /etc/kubernetes/azure.json + readOnly: true + {{- end }} env: - name: KUBECONFIG value: /root/.kubectl/config @@ -74,7 +89,7 @@ spec: {{- end }} args: - --ssh-keygen-dir=/var/fluxd/keygen - - --k8s-secret-name={{ template "flux.fullname" . }}-git-deploy + - --k8s-secret-name={{ .Values.git.secretName | default (printf "%s-git-deploy" (include "flux.fullname" .)) }} - --memcached-hostname={{ template "flux.fullname" . }}-memcached {{- if .Values.memcached.createClusterIP }} - --memcached-service= diff --git a/chart/flux/templates/helm-operator-deployment.yaml b/chart/flux/templates/helm-operator-deployment.yaml index bcbfd42d7..4ec15d8d2 100644 --- a/chart/flux/templates/helm-operator-deployment.yaml +++ b/chart/flux/templates/helm-operator-deployment.yaml @@ -26,6 +26,10 @@ spec: release: {{ .Release.Name }} spec: serviceAccountName: {{ template "flux.serviceAccountName" . }} + {{- if .Values.helmOperator.pullSecret }} + imagePullSecrets: + - name: {{ .Values.helmOperator.pullSecret }} + {{- end }} volumes: {{- if .Values.ssh.known_hosts }} - name: sshdir @@ -100,7 +104,7 @@ spec: - --charts-sync-interval={{ .Values.helmOperator.chartsSyncInterval }} - --update-chart-deps={{ .Values.helmOperator.updateChartDeps }} - --log-release-diffs={{ .Values.helmOperator.logReleaseDiffs }} - {{- if .Values.helmOperator.namespace }} + {{- if .Values.helmOperator.allowNamespace }} - --allow-namespace={{ .Values.helmOperator.allowNamespace }} {{- end }} - --tiller-namespace={{ .Values.helmOperator.tillerNamespace }} diff --git a/chart/flux/templates/memcached.yaml b/chart/flux/templates/memcached.yaml index 7c72417f4..f3a6458c1 100755 --- a/chart/flux/templates/memcached.yaml +++ b/chart/flux/templates/memcached.yaml @@ -21,6 +21,10 @@ spec: app: {{ template "flux.name" . }}-memcached release: {{ .Release.Name }} spec: + {{- if .Values.memcached.pullSecret }} + imagePullSecrets: + - name: {{ .Values.memcached.pullSecret }} + {{- end }} containers: - name: memcached image: {{ .Values.memcached.repository }}:{{ .Values.memcached.tag }} diff --git a/chart/flux/values.yaml b/chart/flux/values.yaml index 8a3e2e50e..b4a2b992c 100644 --- a/chart/flux/values.yaml +++ b/chart/flux/values.yaml @@ -7,8 +7,9 @@ replicaCount: 1 image: repository: quay.io/weaveworks/flux - tag: 1.9.0 + tag: 1.10.0 pullPolicy: IfNotPresent + pullSecret: service: type: ClusterIP @@ -19,8 +20,9 @@ helmOperator: create: false createCRD: true repository: quay.io/weaveworks/helm-operator - tag: 0.5.3 + tag: 0.6.0 pullPolicy: IfNotPresent + pullSecret: # Limit the operator scope to a single namespace allowNamespace: # Update dependencies for charts @@ -52,7 +54,7 @@ helmOperator: # generate a SSH key named identity: ssh-keygen -q -N "" -f ./identity # create a Kubernetes secret: kubectl -n flux create secret generic helm-ssh --from-file=./identity # delete the private key: rm ./identity - # add ./identity.pub as a read-only deployment key in your GitHub repo where the charts are + # add ./identity.pub as a read-only deployment key in your Git repo where the charts are # set the secret name (helm-ssh) below secretName: "" # Additional environment variables to set @@ -114,7 +116,7 @@ git: # generate a SSH key named identity: ssh-keygen -q -N "" -f ./identity # create a Kubernetes secret: kubectl -n flux create secret generic flux-ssh --from-file=./identity # delete the private key: rm ./identity - # add ./identity.pub as a read-only deployment key in your GitHub repo where the charts are + # add ./identity.pub as a deployment key with write access in your Git repo # set the secret name (flux-ssh) below secretName: "" @@ -138,10 +140,15 @@ registry: region: includeId: excludeId: + # Azure ACR settings + acr: + enabled: false + hostPath: /etc/kubernetes/azure.json memcached: repository: memcached tag: 1.4.25 + pullSecret: createClusterIP: true verbose: false maxItemSize: 1m diff --git a/cmd/fluxctl/root_cmd.go b/cmd/fluxctl/root_cmd.go index 65eb9c0fe..a0e146557 100644 --- a/cmd/fluxctl/root_cmd.go +++ b/cmd/fluxctl/root_cmd.go @@ -21,6 +21,7 @@ type rootOpts struct { URL string Token string Namespace string + Labels map[string]string API api.Server } @@ -51,6 +52,7 @@ Workflow: const ( envVariableURL = "FLUX_URL" envVariableNamespace = "FLUX_FORWARD_NAMESPACE" + envVariableLabels = "FLUX_FORWARD_LABELS" envVariableToken = "FLUX_SERVICE_TOKEN" envVariableCloudToken = "WEAVE_CLOUD_TOKEN" defaultURLGivenToken = "https://cloud.weave.works/api/flux" @@ -67,6 +69,8 @@ func (opts *rootOpts) Command() *cobra.Command { cmd.PersistentFlags().StringVar(&opts.Namespace, "k8s-fwd-ns", "default", fmt.Sprintf("Namespace in which fluxd is running, for creating a port forward to access the API. No port forward will be created if a URL or token is given. You can also set the environment variable %s", envVariableNamespace)) + cmd.PersistentFlags().StringToStringVar(&opts.Labels, "k8s-fwd-labels", map[string]string{"app": "flux"}, + fmt.Sprintf("Labels used to select the fluxd pod a port forward should be created for. You can also set the environment variable %s", envVariableLabels)) cmd.PersistentFlags().StringVarP(&opts.URL, "url", "u", "", fmt.Sprintf("Base URL of the flux API (defaults to %q if a token is provided); you can also set the environment variable %s", defaultURLGivenToken, envVariableURL)) cmd.PersistentFlags().StringVarP(&opts.Token, "token", "t", "", @@ -98,9 +102,10 @@ func (opts *rootOpts) PersistentPreRunE(cmd *cobra.Command, _ []string) error { return nil } - opts.Namespace = getFromEnvIfNotSet(cmd.Flags(), "k8s-fwd-ns", opts.Namespace, envVariableNamespace) - opts.Token = getFromEnvIfNotSet(cmd.Flags(), "token", opts.Token, envVariableToken, envVariableCloudToken) - opts.URL = getFromEnvIfNotSet(cmd.Flags(), "url", opts.URL, envVariableURL) + setFromEnvIfNotSet(cmd.Flags(), "k8s-fwd-ns", envVariableNamespace) + setFromEnvIfNotSet(cmd.Flags(), "k8s-fwd-labels", envVariableLabels) + setFromEnvIfNotSet(cmd.Flags(), "token", envVariableToken, envVariableCloudToken) + setFromEnvIfNotSet(cmd.Flags(), "url", envVariableURL) if opts.Token != "" && opts.URL == "" { opts.URL = defaultURLGivenToken @@ -108,6 +113,8 @@ func (opts *rootOpts) PersistentPreRunE(cmd *cobra.Command, _ []string) error { if opts.URL == "" { portforwarder, err := tryPortforwards(opts.Namespace, metav1.LabelSelector{ + MatchLabels: opts.Labels, + }, metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ metav1.LabelSelectorRequirement{ Key: "name", @@ -115,10 +122,6 @@ func (opts *rootOpts) PersistentPreRunE(cmd *cobra.Command, _ []string) error { Values: []string{"flux", "fluxd", "weave-flux-agent"}, }, }, - }, metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app": "flux", - }, }) if err != nil { return err @@ -135,14 +138,13 @@ func (opts *rootOpts) PersistentPreRunE(cmd *cobra.Command, _ []string) error { return nil } -func getFromEnvIfNotSet(flags *pflag.FlagSet, flagName, value string, envNames ...string) string { +func setFromEnvIfNotSet(flags *pflag.FlagSet, flagName string, envNames ...string) { if flags.Changed(flagName) { - return value + return } for _, envName := range envNames { if env := os.Getenv(envName); env != "" { - return env + flags.Set(flagName, env) } } - return value // not changed, so presumably the default } diff --git a/deploy-helm/flux-helm-release-crd.yaml b/deploy-helm/flux-helm-release-crd.yaml index 9cdd49284..4823d443f 100644 --- a/deploy-helm/flux-helm-release-crd.yaml +++ b/deploy-helm/flux-helm-release-crd.yaml @@ -31,6 +31,8 @@ spec: format: int64 resetValues: type: boolean + skipDepUpdate: + type: boolean valueFileSecrets: type: array properties: diff --git a/deploy-helm/helm-operator-deployment.yaml b/deploy-helm/helm-operator-deployment.yaml index 57015e8cd..eb80a7ce4 100644 --- a/deploy-helm/helm-operator-deployment.yaml +++ b/deploy-helm/helm-operator-deployment.yaml @@ -62,7 +62,7 @@ spec: # There are no ":latest" images for helm-operator. Find the most recent # release or image version at https://quay.io/weaveworks/helm-operator # and replace the tag here. - image: quay.io/weaveworks/helm-operator:0.5.3 + image: quay.io/weaveworks/helm-operator:0.6.0 imagePullPolicy: IfNotPresent ports: - name: http diff --git a/deploy-helm/weave-cloud-helm-operator-deployment.yaml b/deploy-helm/weave-cloud-helm-operator-deployment.yaml index 85d0c3693..9e2c53b7f 100644 --- a/deploy-helm/weave-cloud-helm-operator-deployment.yaml +++ b/deploy-helm/weave-cloud-helm-operator-deployment.yaml @@ -27,7 +27,7 @@ spec: secretName: flux-git-deploy containers: - name: flux-helm-operator - image: quay.io/weaveworks/helm-operator:0.5.3 + image: quay.io/weaveworks/helm-operator:0.6.0 imagePullPolicy: IfNotPresent args: - --git-timeout=20s diff --git a/deploy/flux-deployment.yaml b/deploy/flux-deployment.yaml index 56a3c9c4a..0608992f5 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://quay.io/weaveworks/flux # and replace the tag here. - image: quay.io/weaveworks/flux:1.10.0 + image: quay.io/weaveworks/flux:1.10.1 imagePullPolicy: IfNotPresent resources: requests: diff --git a/docker/Dockerfile.flux b/docker/Dockerfile.flux index 5d4025b89..bdf3d658f 100644 --- a/docker/Dockerfile.flux +++ b/docker/Dockerfile.flux @@ -6,7 +6,7 @@ RUN apk add --no-cache openssh ca-certificates tini 'git>=2.3.0' # Add git hosts to known hosts file so we can use # StrickHostKeyChecking with git+ssh -RUN ssh-keyscan github.com gitlab.com bitbucket.org >> /etc/ssh/ssh_known_hosts +RUN ssh-keyscan github.com gitlab.com bitbucket.org ssh.dev.azure.com >> /etc/ssh/ssh_known_hosts # Verify newly added known_hosts (man-in-middle mitigation) ADD ./verify_known_hosts.sh /home/flux/verify_known_hosts.sh diff --git a/docker/Dockerfile.helm-operator b/docker/Dockerfile.helm-operator index c9bcf595e..812c2fb82 100644 --- a/docker/Dockerfile.helm-operator +++ b/docker/Dockerfile.helm-operator @@ -6,7 +6,7 @@ RUN apk add --no-cache openssh ca-certificates tini 'git>=2.3.0' # Add git hosts to known hosts file so we can use # StrickHostKeyChecking with git+ssh -RUN ssh-keyscan github.com gitlab.com bitbucket.org >> /etc/ssh/ssh_known_hosts +RUN ssh-keyscan github.com gitlab.com bitbucket.org ssh.dev.azure.com >> /etc/ssh/ssh_known_hosts # Add default SSH config, which points at the private key we'll mount COPY ./ssh_config /etc/ssh/ssh_config diff --git a/docker/verify_known_hosts.sh b/docker/verify_known_hosts.sh index 3d6022945..686b4ee47 100755 --- a/docker/verify_known_hosts.sh +++ b/docker/verify_known_hosts.sh @@ -7,7 +7,7 @@ known_hosts_file=${known_hosts_file:-/etc/ssh/ssh_known_hosts} # The heredoc below was generated by constructing a known_hosts using # -# ssh-keyscan github.com gitlab.com bitbucket.org > ./known_hosts +# ssh-keyscan github.com gitlab.com bitbucket.org ssh.dev.azure.com > ./known_hosts # # then generating the sorted fingerprints with # @@ -31,6 +31,7 @@ ssh-keygen -l -f ${known_hosts_file} | sort > "$fingerprints" diff - "$fingerprints" <<EOF 2048 SHA256:ROQFvPThGrW4RuWLoL9tq9I9zJ42fK4XywyRtbOz/EQ gitlab.com (RSA) 2048 SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8 github.com (RSA) +2048 SHA256:ohD8VZEXGWo6Ez8GSEJQ9WpafgLFsOfLOtGGQCQo6Og ssh.dev.azure.com (RSA) 2048 SHA256:zzXQOXSRBEiUtuE8AikJYKwbHaxvSc0ojez9YXaGp1A bitbucket.org (RSA) 256 SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw gitlab.com (ECDSA) 256 SHA256:eUXGGm1YGsMAS7vkcx6JOJdOGHPem5gQp4taiCfCLB8 gitlab.com (ED25519) diff --git a/integrations/apis/flux.weave.works/v1beta1/types.go b/integrations/apis/flux.weave.works/v1beta1/types.go index a31dfa6ce..3b74e5f04 100644 --- a/integrations/apis/flux.weave.works/v1beta1/types.go +++ b/integrations/apis/flux.weave.works/v1beta1/types.go @@ -75,6 +75,9 @@ type HelmReleaseSpec struct { // Reset values on helm upgrade // +optional ResetValues bool `json:"resetValues,omitempty"` + // Do not run 'dep' update (assume requirements.yaml is already fulfilled) + // +optional + SkipDepUpdate bool `json:"skipDepUpdate,omitempty"` } // GetTimeout returns the install or upgrade timeout (defaults to 300s) diff --git a/integrations/helm/chartsync/chartsync.go b/integrations/helm/chartsync/chartsync.go index 590e6a0bc..1b95e7c16 100644 --- a/integrations/helm/chartsync/chartsync.go +++ b/integrations/helm/chartsync/chartsync.go @@ -327,7 +327,7 @@ func (chs *ChartChangeSync) reconcileReleaseDef(fhr fluxv1beta1.HelmRelease) { chs.setCondition(&fhr, fluxv1beta1.HelmReleaseChartFetched, v1.ConditionTrue, ReasonCloned, "successfully cloned git repo") chartPath = filepath.Join(chartClone.export.Dir(), chartSource.Path) - if chs.config.UpdateDeps { + if chs.config.UpdateDeps && !fhr.Spec.SkipDepUpdate { if err := updateDependencies(chartPath, ""); err != nil { chs.setCondition(&fhr, fluxv1beta1.HelmReleaseReleased, v1.ConditionFalse, ReasonDependencyFailed, err.Error()) chs.logger.Log("warning", "Failed to update chart dependencies", "namespace", fhr.Namespace, "name", fhr.Name, "error", err) diff --git a/registry/azure.go b/registry/azure.go new file mode 100644 index 000000000..61884813b --- /dev/null +++ b/registry/azure.go @@ -0,0 +1,53 @@ +package registry + +import ( + "encoding/json" + "io/ioutil" + "strings" +) + +const ( + // Mount volume from hostpath. + azureCloudConfigJsonFile = "/etc/kubernetes/azure.json" +) + +type azureCloudConfig struct { + AADClientId string `json:"aadClientId"` + AADClientSecret string `json:"aadClientSecret"` +} + +// Fetch Azure Active Directory clientid/secret pair from azure.json, usable for container registry authentication. +// +// Note: azure.json is populated by AKS/AKS-Engine script kubernetesconfigs.sh. The file is then passed to kubelet via +// --azure-container-registry-config=/etc/kubernetes/azure.json, parsed by kubernetes/kubernetes' azure_credentials.go +// https://github.com/kubernetes/kubernetes/issues/58034 seeks to deprecate this kubelet command-line argument, possibly +// replacing it with managed identity for the Node VMs. See https://github.com/Azure/acr/blob/master/docs/AAD-OAuth.md +func getAzureCloudConfigAADToken(host string) (creds, error) { + jsonFile, err := ioutil.ReadFile(azureCloudConfigJsonFile) + if err != nil { + return creds{}, err + } + + var token azureCloudConfig + + err = json.Unmarshal(jsonFile, &token) + if err != nil { + return creds{}, err + } + + return creds{ + registry: host, + provenance: "azure.json", + username: token.AADClientId, + password: token.AADClientSecret}, nil +} + +// List from https://github.com/kubernetes/kubernetes/blob/master/pkg/credentialprovider/azure/azure_credentials.go +func hostIsAzureContainerRegistry(host string) bool { + for _, v := range []string{".azurecr.io", ".azurecr.cn", ".azurecr.de", ".azurecr.us"} { + if strings.HasSuffix(host, v) { + return true + } + } + return false +} diff --git a/registry/azure_test.go b/registry/azure_test.go new file mode 100644 index 000000000..7a670c10e --- /dev/null +++ b/registry/azure_test.go @@ -0,0 +1,56 @@ +package registry + +import ( + "testing" +) + +func Test_HostIsAzureContainerRegistry(t *testing.T) { + for _, v := range []struct { + host string + isACR bool + }{ + { + host: "azurecr.io", + isACR: false, + }, + { + host: "", + isACR: false, + }, + { + host: "gcr.io", + isACR: false, + }, + { + host: "notazurecr.io", + isACR: false, + }, + { + host: "example.azurecr.io.not", + isACR: false, + }, + // Public cloud + { + host: "example.azurecr.io", + isACR: true, + }, + // Sovereign clouds + { + host: "example.azurecr.cn", + isACR: true, + }, + { + host: "example.azurecr.de", + isACR: true, + }, + { + host: "example.azurecr.us", + isACR: true, + }, + } { + result := hostIsAzureContainerRegistry(v.host) + if result != v.isACR { + t.Fatalf("For test %q, expected isACR = %v but got %v", v.host, v.isACR, result) + } + } +} diff --git a/registry/credentials.go b/registry/credentials.go index 278568bca..b8c49616c 100644 --- a/registry/credentials.go +++ b/registry/credentials.go @@ -144,6 +144,13 @@ func (cs Credentials) credsFor(host string) creds { return cred } } + + if hostIsAzureContainerRegistry(host) { + if cred, err := getAzureCloudConfigAADToken(host); err == nil { + return cred + } + } + return creds{} } diff --git a/site/faq.md b/site/faq.md index b86ba28dc..effb5492b 100644 --- a/site/faq.md +++ b/site/faq.md @@ -22,7 +22,7 @@ menu_order: 60 * [How do I use my own deploy key?](#how-do-i-use-my-own-deploy-key) * [Why are my images not showing up in the list of images?](#why-are-my-images-not-showing-up-in-the-list-of-images) * [Why do my image tags appear out of order?](#why-do-my-image-tags-appear-out-of-order) - * [How do I use a private git host (or one that's not github.com, gitlab.com, or bitbucket.org)?](#how-do-i-use-a-private-git-host-or-one-thats-not-githubcom-gitlabcom-or-bitbucketorg) + * [How do I use a private git host (or one that's not github.com, gitlab.com, bitbucket.org, or dev.azure.com)?](#how-do-i-use-a-private-git-host-or-one-thats-not-githubcom-gitlabcom-bitbucketorg-or-devazurecom) * [Will Flux delete resources that are no longer in the git repository?](#will-flux-delete-resources-that-are-no-longer-in-the-git-repository) * [Why does my CI pipeline keep getting triggered?](#why-does-my-ci-pipeline-keep-getting-triggered) * [What is the "sync tag"; or, why do I see a `flux-sync` tag in my git repo?](#what-is-the-sync-tag-or-why-do-i-see-a-flux-sync-tag-in-my-git-repo) @@ -247,7 +247,7 @@ happen: if you've only just started using a particular image in a workload. - Flux can't get suitable credentials for the image repository. At present, it looks at `imagePullSecret`s attached to workloads, - service accounts, platform-provided credentials on GCP or AWS, and + service accounts, platform-provided credentials on GCP, AWS or Azure, and a Docker config file if you mount one into the fluxd container (see the [command-line usage](./daemon.md)). - When using images in ECR, from EC2, the `NodeInstanceRole` for the @@ -257,6 +257,25 @@ happen: [`kops`](https://github.com/kubernetes/kops) (with [`.iam.allowContainerRegistry=true`](https://github.com/kubernetes/kops/blob/master/docs/iam_roles.md#iam-roles)) both make sure this is the case. + - When using images from ACR in AKS, the HostPath `/etc/kubernetes/azure.json` + should be [mounted](https://kubernetes.io/docs/concepts/storage/volumes/) into the Flux Pod. + Set `registry.acr.enabled=True` in the [helm chart](../chart/flux/README.md) + or alter the [Deployment](../deploy/flux-deployment.yaml): + ```yaml + spec: + containers: + image: quay.io/weaveworks/flux + ... + volumeMounts: + - name: acr-credentials + mountPath: /etc/kubernetes/azure.json + readOnly: true + volumes: + - name: acr-credentials + hostPath: + path: /etc/kubernetes/azure.json + type: "" + ``` - Flux excludes images with no suitable manifest (linux amd64) in manifestlist - Flux doesn't yet understand image refs that use digests instead of tags; see @@ -285,14 +304,14 @@ build has its own creation time is to label it with a build time; e.g., using [OpenContainers pre-defined annotations](https://github.com/opencontainers/image-spec/blob/master/annotations.md#pre-defined-annotation-keys). -### How do I use a private git host (or one that's not github.com, gitlab.com, or bitbucket.org)? +### How do I use a private git host (or one that's not github.com, gitlab.com, bitbucket.org, or dev.azure.com)? As part of using git+ssh securely from the Flux daemon, we make sure `StrictHostKeyChecking` is on in the [SSH config](http://man7.org/linux/man-pages/man5/ssh_config.5.html). This mitigates against man-in-the-middle attacks. -We bake host keys for `github.com`, `gitlab.com`, and `bitbucket.org` +We bake host keys for `github.com`, `gitlab.com`, `bitbucket.org`, and `dev.azure.com` into the image to cover some common cases. If you're using another service, or running your own git host, you need to supply your own host key(s). @@ -333,6 +352,7 @@ Here's the relevant docs for some common CI systems: - [TravisCI](https://docs.travis-ci.com/user/customizing-the-build#Building-Specific-Branches) - [GitLab](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified) - [Bitbucket Pipelines](https://confluence.atlassian.com/bitbucket/configure-bitbucket-pipelines-yml-792298910.html#Configurebitbucket-pipelines.yml-ci_defaultdefault) + - [Azure Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/index?view=azure-devops) ### What is the "sync tag"; or, why do I see a `flux-sync` tag in my git repo? diff --git a/site/helm-get-started.md b/site/helm-get-started.md index d3208cc44..99aa34343 100644 --- a/site/helm-get-started.md +++ b/site/helm-get-started.md @@ -79,7 +79,7 @@ In this next step you install Weave Flux using `helm`. Simply *Just make sure you replace `YOURUSER` with your GitHub username in the command below:* - - Using a public git server from `bitbucket.com`, `github.com` or `gitlab.com`: + - Using a public git server from `bitbucket.com`, `github.com`, `gitlab.com` or `dev.azure.com`: ```sh helm upgrade -i flux \ diff --git a/site/troubleshooting.md b/site/troubleshooting.md index 4e084029b..75ccffea4 100644 --- a/site/troubleshooting.md +++ b/site/troubleshooting.md @@ -48,8 +48,7 @@ This means Flux can't read from and write to the git repo. Check that - ... that the host where your git repo lives is in `~/.ssh/known_hosts` in the fluxd container. We prime the container - _image_ with host keys for `github.com`, `gitlab.com` and - `bitbucket.org`, but if you're using your own git server, you'll + _image_ with host keys for `github.com`, `gitlab.com`, `bitbucket.org`, and `dev.azure.com`, but if you're using your own git server, you'll need to add its host key. See [./standalone-setup.md](./standalone-setup.md#using-a-private-git-host).