mirror of
https://github.com/fluxcd/flux2.git
synced 2026-02-09 09:17:27 +00:00
Merge branch 'main' into let-user-set-version-to-install
This commit is contained in:
commit
641d5378f8
94 changed files with 4241 additions and 335 deletions
1
.github/aur/flux-bin/.SRCINFO.template
vendored
1
.github/aur/flux-bin/.SRCINFO.template
vendored
|
|
@ -8,7 +8,6 @@ pkgbase = flux-bin
|
|||
arch = armv7h
|
||||
arch = aarch64
|
||||
license = APACHE
|
||||
optdepends = kubectl
|
||||
source_x86_64 = flux-bin-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v1/flux_${PKGVER}_linux_amd64.tar.gz
|
||||
source_armv6h = flux-bin-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v1/flux_${PKGVER}_linux_arm.tar.gz
|
||||
source_armv7h = flux-bin-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v1/flux_${PKGVER}_linux_arm.tar.gz
|
||||
|
|
|
|||
3
.github/aur/flux-bin/PKGBUILD.template
vendored
3
.github/aur/flux-bin/PKGBUILD.template
vendored
|
|
@ -8,8 +8,7 @@ pkgdesc="Open and extensible continuous delivery solution for Kubernetes"
|
|||
url="https://fluxcd.io/"
|
||||
arch=("x86_64" "armv6h" "armv7h" "aarch64")
|
||||
license=("APACHE")
|
||||
optdepends=('kubectl: for apply actions on the Kubernetes cluster',
|
||||
'bash-completion: auto-completion for flux in Bash',
|
||||
optdepends=('bash-completion: auto-completion for flux in Bash',
|
||||
'zsh-completions: auto-completion for flux in ZSH')
|
||||
source_x86_64=(
|
||||
"${pkgname}-${pkgver}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${pkgver}/flux_${pkgver}_linux_amd64.tar.gz"
|
||||
|
|
|
|||
1
.github/aur/flux-go/.SRCINFO.template
vendored
1
.github/aur/flux-go/.SRCINFO.template
vendored
|
|
@ -10,7 +10,6 @@ pkgbase = flux-go
|
|||
license = APACHE
|
||||
makedepends = go
|
||||
depends = glibc
|
||||
optdepends = kubectl
|
||||
provides = flux-bin
|
||||
conflicts = flux-bin
|
||||
replaces = flux-cli
|
||||
|
|
|
|||
3
.github/aur/flux-go/PKGBUILD.template
vendored
3
.github/aur/flux-go/PKGBUILD.template
vendored
|
|
@ -13,8 +13,7 @@ conflicts=("flux-bin")
|
|||
replaces=("flux-cli")
|
||||
depends=("glibc")
|
||||
makedepends=('go>=1.16', 'kustomize>=3.0')
|
||||
optdepends=('kubectl: for apply actions on the Kubernetes cluster',
|
||||
'bash-completion: auto-completion for flux in Bash',
|
||||
optdepends=('bash-completion: auto-completion for flux in Bash',
|
||||
'zsh-completions: auto-completion for flux in ZSH')
|
||||
source=(
|
||||
"${pkgname}-${pkgver}.tar.gz::https://github.com/fluxcd/flux2/archive/v${pkgver}.tar.gz"
|
||||
|
|
|
|||
1
.github/aur/flux-scm/.SRCINFO.template
vendored
1
.github/aur/flux-scm/.SRCINFO.template
vendored
|
|
@ -10,7 +10,6 @@ pkgbase = flux-scm
|
|||
license = APACHE
|
||||
makedepends = go
|
||||
depends = glibc
|
||||
optdepends = kubectl
|
||||
provides = flux-bin
|
||||
conflicts = flux-bin
|
||||
source = git+https://github.com/fluxcd/flux2.git
|
||||
|
|
|
|||
3
.github/aur/flux-scm/PKGBUILD.template
vendored
3
.github/aur/flux-scm/PKGBUILD.template
vendored
|
|
@ -12,8 +12,7 @@ provides=("flux-bin")
|
|||
conflicts=("flux-bin")
|
||||
depends=("glibc")
|
||||
makedepends=('go>=1.16', 'kustomize>=3.0')
|
||||
optdepends=('kubectl: for apply actions on the Kubernetes cluster',
|
||||
'bash-completion: auto-completion for flux in Bash',
|
||||
optdepends=('bash-completion: auto-completion for flux in Bash',
|
||||
'zsh-completions: auto-completion for flux in ZSH')
|
||||
source=(
|
||||
"git+https://github.com/fluxcd/flux2.git"
|
||||
|
|
|
|||
66
.github/workflows/e2e-azure.yaml
vendored
Normal file
66
.github/workflows/e2e-azure.yaml
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
name: e2e-azure
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 6 * * *'
|
||||
push:
|
||||
branches: [ azure* ]
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Restore Go cache
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go1.16-
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16.x
|
||||
- name: Install libgit2
|
||||
run: |
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 648ACFD622F3D138
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0E98404D386FA1D9
|
||||
echo "deb http://deb.debian.org/debian unstable main" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb-src http://deb.debian.org/debian unstable main" | sudo tee -a /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-downgrades libgit2-dev/unstable zlib1g-dev/unstable libssh2-1-dev/unstable libpcre3-dev/unstable
|
||||
- name: Setup Flux CLI
|
||||
run: |
|
||||
make build
|
||||
mkdir -p $HOME/.local/bin
|
||||
mv ./bin/flux $HOME/.local/bin
|
||||
- name: Setup SOPS
|
||||
run: |
|
||||
wget https://github.com/mozilla/sops/releases/download/v3.7.1/sops-v3.7.1.linux
|
||||
chmod +x sops-v3.7.1.linux
|
||||
mkdir -p $HOME/.local/bin
|
||||
mv sops-v3.7.1.linux $HOME/.local/bin/sops
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@v1
|
||||
with:
|
||||
terraform_version: 1.0.7
|
||||
terraform_wrapper: false
|
||||
- name: Setup Azure CLI
|
||||
run: |
|
||||
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
||||
- name: Run Azure e2e tests
|
||||
env:
|
||||
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
|
||||
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
|
||||
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
|
||||
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
|
||||
run: |
|
||||
echo $HOME
|
||||
echo $PATH
|
||||
ls $HOME/.local/bin
|
||||
az login --service-principal -u ${ARM_CLIENT_ID} -p ${ARM_CLIENT_SECRET} -t ${ARM_TENANT_ID}
|
||||
cd ./tests/azure
|
||||
go test -v -coverprofile cover.out -timeout 60m .
|
||||
3
.github/workflows/e2e.yaml
vendored
3
.github/workflows/e2e.yaml
vendored
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
uses: engineerd/setup-kind@v0.5.0
|
||||
with:
|
||||
version: v0.11.1
|
||||
image: kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
|
||||
image: kindest/node:v1.19.11@sha256:07db187ae84b4b7de440a73886f008cf903fcf5764ba8106a9fd5243d6f32729
|
||||
config: .github/kind/config.yaml # disable KIND-net
|
||||
- name: Setup envtest
|
||||
uses: fluxcd/pkg/actions/envtest@main
|
||||
|
|
@ -93,7 +93,6 @@ jobs:
|
|||
--path="./deploy/overlays/dev" \
|
||||
--prune=true \
|
||||
--interval=5m \
|
||||
--validation=client \
|
||||
--health-check="Deployment/frontend.dev" \
|
||||
--health-check="Deployment/backend.dev" \
|
||||
--health-check-timeout=3m
|
||||
|
|
|
|||
|
|
@ -49,9 +49,17 @@ brews:
|
|||
folder: Formula
|
||||
homepage: "https://fluxcd.io/"
|
||||
description: "Flux CLI"
|
||||
dependencies:
|
||||
- name: kubectl
|
||||
type: optional
|
||||
install: |
|
||||
bin.install "flux"
|
||||
|
||||
bash_output = Utils.safe_popen_read(bin/"flux", "completion", "bash")
|
||||
(bash_completion/"flux").write bash_output
|
||||
|
||||
zsh_output = Utils.safe_popen_read(bin/"flux", "completion", "zsh")
|
||||
(zsh_completion/"_flux").write zsh_output
|
||||
|
||||
fish_output = Utils.safe_popen_read(bin/"flux", "completion", "fish")
|
||||
(fish_completion/"flux.fish").write fish_output
|
||||
test: |
|
||||
system "#{bin}/flux --version"
|
||||
publishers:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ FROM alpine:3.13 as builder
|
|||
RUN apk add --no-cache ca-certificates curl
|
||||
|
||||
ARG ARCH=linux/amd64
|
||||
ARG KUBECTL_VER=1.20.4
|
||||
ARG KUBECTL_VER=1.22.2
|
||||
|
||||
RUN curl -sL https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/${ARCH}/kubectl \
|
||||
-o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl && \
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"crypto/elliptic"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
|
@ -67,6 +68,10 @@ type bootstrapFlags struct {
|
|||
authorName string
|
||||
authorEmail string
|
||||
|
||||
gpgKeyRingPath string
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
|
||||
commitMessageAppendix string
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +123,10 @@ func init() {
|
|||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.authorName, "author-name", "Flux", "author name for Git commits")
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.authorEmail, "author-email", "", "author email for Git commits")
|
||||
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.gpgKeyRingPath, "gpg-key-ring", "", "path to GPG key ring for signing commits")
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.gpgPassphrase, "gpg-passphrase", "", "passphrase for decrypting GPG private key")
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.gpgKeyID, "gpg-key-id", "", "key id for selecting a particular key")
|
||||
|
||||
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.commitMessageAppendix, "commit-message-appendix", "", "string to add to the commit messages, e.g. '[ci skip]'")
|
||||
|
||||
bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.arch, "arch", bootstrapArgs.arch.Description())
|
||||
|
|
@ -174,6 +183,10 @@ func mapTeamSlice(s []string, defaultPermission string) map[string]string {
|
|||
m := make(map[string]string, len(s))
|
||||
for _, v := range s {
|
||||
m[v] = defaultPermission
|
||||
if s := strings.Split(v, ":"); len(s) == 2 {
|
||||
m[s[0]] = s[1]
|
||||
}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,8 +171,14 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||
secretOpts.ECDSACurve = bootstrapArgs.keyECDSACurve.Curve
|
||||
|
||||
// Configure repository URL to match auth config for sync.
|
||||
repositoryURL.User = url.User(gitArgs.username)
|
||||
// Configure repository URL to match auth config for sync
|
||||
|
||||
// Override existing user when user is not already set
|
||||
// or when a username was passed in
|
||||
if repositoryURL.User == nil || gitArgs.username != "git" {
|
||||
repositoryURL.User = url.User(gitArgs.username)
|
||||
}
|
||||
|
||||
repositoryURL.Scheme = "ssh"
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
repositoryURL.Host = bootstrapArgs.sshHostname
|
||||
|
|
@ -218,6 +224,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
|||
bootstrap.WithPostGenerateSecretFunc(promptPublicKey),
|
||||
bootstrap.WithLogger(logger),
|
||||
bootstrap.WithCABundle(caBundle),
|
||||
bootstrap.WithGitCommitSigning(bootstrapArgs.gpgKeyRingPath, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ the bootstrap command will perform an upgrade if needed.`,
|
|||
# Run bootstrap for a private repository and assign organization teams to it
|
||||
flux bootstrap github --owner=<organization> --repository=<repository name> --team=<team1 slug> --team=<team2 slug>
|
||||
|
||||
# Run bootstrap for a private repository and assign organization teams with their access level(e.g maintain, admin) to it
|
||||
flux bootstrap github --owner=<organization> --repository=<repository name> --team=<team1 slug>:<access-level>
|
||||
|
||||
# Run bootstrap for a repository path
|
||||
flux bootstrap github --owner=<organization> --repository=<repository name> --path=dev-cluster
|
||||
|
||||
|
|
@ -93,7 +96,7 @@ var githubArgs githubFlags
|
|||
func init() {
|
||||
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.owner, "owner", "", "GitHub user or organization name")
|
||||
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.repository, "repository", "", "GitHub repository name")
|
||||
bootstrapGitHubCmd.Flags().StringSliceVar(&githubArgs.teams, "team", []string{}, "GitHub team to be given maintainer access (also accepts comma-separated values)")
|
||||
bootstrapGitHubCmd.Flags().StringSliceVar(&githubArgs.teams, "team", []string{}, "GitHub team and the access to be given to it(team:maintain). Defaults to maintainer access if no access level is specified (also accepts comma-separated values)")
|
||||
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.personal, "personal", false, "if true, the owner is assumed to be a GitHub user; otherwise an org")
|
||||
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.private, "private", true, "if true, the repository is setup or configured as private")
|
||||
bootstrapGitHubCmd.Flags().DurationVar(&githubArgs.interval, "interval", time.Minute, "sync interval")
|
||||
|
|
|
|||
|
|
@ -18,15 +18,12 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/spf13/cobra"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
|
|
@ -56,8 +53,11 @@ type checkFlags struct {
|
|||
extraComponents []string
|
||||
}
|
||||
|
||||
type kubectlVersion struct {
|
||||
ClientVersion *apimachineryversion.Info `json:"clientVersion"`
|
||||
var kubernetesConstraints = []string{
|
||||
">=1.19.0-0",
|
||||
">=1.16.11-0 <=1.16.15-0",
|
||||
">=1.17.7-0 <=1.17.17-0",
|
||||
">=1.18.4-0 <=1.18.20-0",
|
||||
}
|
||||
|
||||
var checkArgs checkFlags
|
||||
|
|
@ -73,19 +73,12 @@ func init() {
|
|||
}
|
||||
|
||||
func runCheckCmd(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
logger.Actionf("checking prerequisites")
|
||||
checkFailed := false
|
||||
|
||||
fluxCheck()
|
||||
|
||||
if !kubectlCheck(ctx, ">=1.18.0-0") {
|
||||
checkFailed = true
|
||||
}
|
||||
|
||||
if !kubernetesCheck(">=1.16.0-0") {
|
||||
if !kubernetesCheck(kubernetesConstraints) {
|
||||
checkFailed = true
|
||||
}
|
||||
|
||||
|
|
@ -130,43 +123,7 @@ func fluxCheck() {
|
|||
}
|
||||
}
|
||||
|
||||
func kubectlCheck(ctx context.Context, constraint string) bool {
|
||||
_, err := exec.LookPath("kubectl")
|
||||
if err != nil {
|
||||
logger.Failuref("kubectl not found")
|
||||
return false
|
||||
}
|
||||
|
||||
kubectlArgs := []string{"version", "--client", "--output", "json"}
|
||||
output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
|
||||
if err != nil {
|
||||
logger.Failuref("kubectl version can't be determined")
|
||||
return false
|
||||
}
|
||||
|
||||
kv := &kubectlVersion{}
|
||||
if err = json.Unmarshal([]byte(output), kv); err != nil {
|
||||
logger.Failuref("kubectl version output can't be unmarshalled")
|
||||
return false
|
||||
}
|
||||
|
||||
v, err := version.ParseVersion(kv.ClientVersion.GitVersion)
|
||||
if err != nil {
|
||||
logger.Failuref("kubectl version can't be parsed")
|
||||
return false
|
||||
}
|
||||
|
||||
c, _ := semver.NewConstraint(constraint)
|
||||
if !c.Check(v) {
|
||||
logger.Failuref("kubectl version %s < %s", v.Original(), constraint)
|
||||
return false
|
||||
}
|
||||
|
||||
logger.Successf("kubectl %s %s", v.String(), constraint)
|
||||
return true
|
||||
}
|
||||
|
||||
func kubernetesCheck(constraint string) bool {
|
||||
func kubernetesCheck(constraints []string) bool {
|
||||
cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
|
||||
if err != nil {
|
||||
logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
|
||||
|
|
@ -191,13 +148,23 @@ func kubernetesCheck(constraint string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
c, _ := semver.NewConstraint(constraint)
|
||||
if !c.Check(v) {
|
||||
logger.Failuref("Kubernetes version %s < %s", v.Original(), constraint)
|
||||
var valid bool
|
||||
var vrange string
|
||||
for _, constraint := range constraints {
|
||||
c, _ := semver.NewConstraint(constraint)
|
||||
if c.Check(v) {
|
||||
valid = true
|
||||
vrange = constraint
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
logger.Failuref("Kubernetes version %s does not match %s", v.Original(), constraints[0])
|
||||
return false
|
||||
}
|
||||
|
||||
logger.Successf("Kubernetes %s %s", v.String(), constraint)
|
||||
logger.Successf("Kubernetes %s %s", v.String(), vrange)
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,11 @@ func TestCheckPre(t *testing.T) {
|
|||
t.Fatalf("Error unmarshalling: %v", err.Error())
|
||||
}
|
||||
|
||||
clientVersion := strings.TrimPrefix(versions["clientVersion"].GitVersion, "v")
|
||||
serverVersion := strings.TrimPrefix(versions["serverVersion"].GitVersion, "v")
|
||||
|
||||
cmd := cmdTestCase{
|
||||
args: "check --pre",
|
||||
assert: assertGoldenTemplateFile("testdata/check/check_pre.golden", map[string]string{
|
||||
"clientVersion": clientVersion,
|
||||
"serverVersion": serverVersion,
|
||||
}),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,9 +187,11 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
|
||||
if helmReleaseArgs.createNamespace {
|
||||
helmRelease.Spec.Install = &helmv2.Install{
|
||||
CreateNamespace: helmReleaseArgs.createNamespace,
|
||||
if helmRelease.Spec.Install == nil {
|
||||
helmRelease.Spec.Install = &helmv2.Install{}
|
||||
}
|
||||
|
||||
helmRelease.Spec.Install.CreateNamespace = helmReleaseArgs.createNamespace
|
||||
}
|
||||
|
||||
if helmReleaseArgs.saName != "" {
|
||||
|
|
@ -197,6 +199,10 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
|
||||
if helmReleaseArgs.crds != "" {
|
||||
if helmRelease.Spec.Install == nil {
|
||||
helmRelease.Spec.Install = &helmv2.Install{}
|
||||
}
|
||||
|
||||
helmRelease.Spec.Install.CRDs = helmv2.Create
|
||||
helmRelease.Spec.Upgrade = &helmv2.Upgrade{CRDs: helmv2.CRDsPolicy(helmReleaseArgs.crds.String())}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
|
|||
Labels: labels,
|
||||
},
|
||||
Spec: imagev1.ImagePolicySpec{
|
||||
ImageRepositoryRef: meta.LocalObjectReference{
|
||||
ImageRepositoryRef: meta.NamespacedObjectReference{
|
||||
Name: imagePolicyArgs.imageRef,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/flags"
|
||||
|
|
@ -49,7 +49,6 @@ var createKsCmd = &cobra.Command{
|
|||
--path="./examples/contour/" \
|
||||
--prune=true \
|
||||
--interval=10m \
|
||||
--validation=client \
|
||||
--health-check="Deployment/contour.projectcontour" \
|
||||
--health-check="DaemonSet/envoy.projectcontour" \
|
||||
--health-check-timeout=3m
|
||||
|
|
@ -60,8 +59,7 @@ var createKsCmd = &cobra.Command{
|
|||
--source=GitRepository/webapp \
|
||||
--path="./deploy/overlays/dev" \
|
||||
--prune=true \
|
||||
--interval=5m \
|
||||
--validation=client
|
||||
--interval=5m
|
||||
|
||||
# Create a Kustomization using a source from a different namespace
|
||||
flux create kustomization podinfo \
|
||||
|
|
@ -69,8 +67,7 @@ var createKsCmd = &cobra.Command{
|
|||
--source=GitRepository/podinfo.flux-system \
|
||||
--path="./deploy/overlays/dev" \
|
||||
--prune=true \
|
||||
--interval=5m \
|
||||
--validation=client
|
||||
--interval=5m
|
||||
|
||||
# Create a Kustomization resource that references a Bucket
|
||||
flux create kustomization secrets \
|
||||
|
|
@ -108,6 +105,8 @@ func init() {
|
|||
createKsCmd.Flags().Var(&kustomizationArgs.decryptionProvider, "decryption-provider", kustomizationArgs.decryptionProvider.Description())
|
||||
createKsCmd.Flags().StringVar(&kustomizationArgs.decryptionSecret, "decryption-secret", "", "set the Kubernetes secret name that contains the OpenPGP private keys used for sops decryption")
|
||||
createKsCmd.Flags().StringVar(&kustomizationArgs.targetNamespace, "target-namespace", "", "overrides the namespace of all Kustomization objects reconciled by this Kustomization")
|
||||
createKsCmd.Flags().MarkDeprecated("validation", "this arg is no longer used, all resources are validated using server-side apply dry-run")
|
||||
|
||||
createCmd.AddCommand(createKsCmd)
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +157,6 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
|
|||
Namespace: kustomizationArgs.source.Namespace,
|
||||
},
|
||||
Suspend: false,
|
||||
Validation: kustomizationArgs.validation,
|
||||
TargetNamespace: kustomizationArgs.targetNamespace,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package main
|
|||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var deleteKsCmd = &cobra.Command{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var exportKsCmd = &cobra.Command{
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
utils.PrintTable(cmd.OutOrStderr(), header, rows)
|
||||
utils.PrintTable(cmd.OutOrStdout(), header, rows)
|
||||
|
||||
if getAll {
|
||||
fmt.Println()
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var getKsCmd = &cobra.Command{
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@ If a previous version is installed, then an in-place upgrade will be performed.`
|
|||
flux install --version=latest --namespace=flux-system
|
||||
|
||||
# Install a specific version and a series of components
|
||||
flux install --dry-run --version=v0.0.7 --components="source-controller,kustomize-controller"
|
||||
flux install --version=v0.0.7 --components="source-controller,kustomize-controller"
|
||||
|
||||
# Install Flux onto tainted Kubernetes nodes
|
||||
flux install --toleration-keys=node.kubernetes.io/dedicated-to-flux
|
||||
|
||||
# Dry-run install with manifests preview
|
||||
flux install --dry-run --verbose
|
||||
# Dry-run install
|
||||
flux install --export | kubectl apply --dry-run=client -f-
|
||||
|
||||
# Write install manifests to file
|
||||
flux install --export > flux-system.yaml`,
|
||||
|
|
@ -102,6 +102,7 @@ func init() {
|
|||
"list of toleration keys used to schedule the components pods onto nodes with matching taints")
|
||||
installCmd.Flags().MarkHidden("manifests")
|
||||
installCmd.Flags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64")
|
||||
installCmd.Flags().MarkDeprecated("dry-run", "use 'flux install --export | kubectl apply --dry-run=client -f-'")
|
||||
rootCmd.AddCommand(installCmd)
|
||||
}
|
||||
|
||||
|
|
@ -188,25 +189,19 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
|
|||
|
||||
logger.Successf("manifests build completed")
|
||||
logger.Actionf("installing components in %s namespace", rootArgs.namespace)
|
||||
applyOutput := utils.ModeStderrOS
|
||||
if rootArgs.verbose {
|
||||
applyOutput = utils.ModeOS
|
||||
}
|
||||
|
||||
kubectlArgs := []string{"apply", "-f", filepath.Join(tmpDir, manifest.Path)}
|
||||
if installArgs.dryRun {
|
||||
kubectlArgs = append(kubectlArgs, "--dry-run=client")
|
||||
applyOutput = utils.ModeOS
|
||||
}
|
||||
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
|
||||
return fmt.Errorf("install failed: %w", err)
|
||||
}
|
||||
|
||||
if installArgs.dryRun {
|
||||
logger.Successf("install dry-run finished")
|
||||
return nil
|
||||
}
|
||||
|
||||
applyOutput, err := utils.Apply(ctx, rootArgs.kubeconfig, rootArgs.kubecontext, filepath.Join(tmpDir, manifest.Path))
|
||||
if err != nil {
|
||||
return fmt.Errorf("install failed: %w", err)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, applyOutput)
|
||||
|
||||
kubeConfig, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
|
||||
if err != nil {
|
||||
return fmt.Errorf("install failed: %w", err)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package main
|
|||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
// kustomizev1.Kustomization
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ func TestKustomizationFromGit(t *testing.T) {
|
|||
"testdata/kustomization/create_source_git.golden",
|
||||
},
|
||||
{
|
||||
"create kustomization tkfg --source=tkfg --path=./deploy/overlays/dev --prune=true --interval=5m --validation=client --health-check=Deployment/frontend.dev --health-check=Deployment/backend.dev --health-check-timeout=3m",
|
||||
"create kustomization tkfg --source=tkfg --path=./deploy/overlays/dev --prune=true --interval=5m --health-check=Deployment/frontend.dev --health-check=Deployment/backend.dev --health-check-timeout=3m",
|
||||
"testdata/kustomization/create_kustomization_from_git.golden",
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"html/template"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -34,6 +35,7 @@ import (
|
|||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/kubectl/pkg/util"
|
||||
"k8s.io/kubectl/pkg/util/podutils"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/flags"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
|
|
@ -174,7 +176,17 @@ func getPods(ctx context.Context, c *kubernetes.Clientset, label string) ([]core
|
|||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
ret = append(ret, podList.Items...)
|
||||
pods := []*corev1.Pod{}
|
||||
for i := range podList.Items {
|
||||
pod := podList.Items[i]
|
||||
pods = append(pods, &pod)
|
||||
}
|
||||
|
||||
if len(pods) > 0 {
|
||||
// sort pods to prioritize running pods over others
|
||||
sort.Sort(podutils.ByLogging(pods))
|
||||
ret = append(ret, *pods[0])
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.`,
|
|||
flux check --pre
|
||||
|
||||
# Install the latest version of Flux
|
||||
flux install --version=master
|
||||
flux install
|
||||
|
||||
# Create a source for a public Git repository
|
||||
flux create source git webapp-latest \
|
||||
|
|
@ -66,7 +66,6 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.`,
|
|||
--path="./deploy/webapp/" \
|
||||
--prune=true \
|
||||
--interval=5m \
|
||||
--validation=client \
|
||||
--health-check="Deployment/backend.webapp" \
|
||||
--health-check="Deployment/frontend.webapp" \
|
||||
--health-check-timeout=2m
|
||||
|
|
|
|||
|
|
@ -116,11 +116,13 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
|
|||
reconciliationHandled(ctx, kubeClient, namespacedName, reconcile.object, lastHandledReconcileAt)); err != nil {
|
||||
return err
|
||||
}
|
||||
readyCond := apimeta.FindStatusCondition(*reconcile.object.GetStatusConditions(), meta.ReadyCondition)
|
||||
if readyCond == nil {
|
||||
return fmt.Errorf("status can't be determined")
|
||||
}
|
||||
|
||||
logger.Successf("%s reconciliation completed", reconcile.kind)
|
||||
|
||||
if apimeta.IsStatusConditionFalse(*reconcile.object.GetStatusConditions(), meta.ReadyCondition) {
|
||||
return fmt.Errorf("%s reconciliation failed", reconcile.kind)
|
||||
if readyCond.Status != metav1.ConditionTrue {
|
||||
return fmt.Errorf("%s reconciliation failed: ''%s", reconcile.kind, readyCond.Message)
|
||||
}
|
||||
logger.Successf(reconcile.object.successMessage())
|
||||
return nil
|
||||
|
|
@ -133,7 +135,9 @@ func reconciliationHandled(ctx context.Context, kubeClient client.Client,
|
|||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return obj.lastHandledReconcileRequest() != lastHandledReconcileAt, nil
|
||||
isProgressing := apimeta.IsStatusConditionPresentAndEqual(*obj.GetStatusConditions(),
|
||||
meta.ReadyCondition, metav1.ConditionUnknown)
|
||||
return obj.lastHandledReconcileRequest() != lastHandledReconcileAt && !isProgressing, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
|
|
@ -68,22 +69,26 @@ func (reconcile reconcileWithSourceCommand) run(cmd *cobra.Command, args []strin
|
|||
rootArgs.namespace = nsCopy
|
||||
}
|
||||
|
||||
lastHandledReconcileAt := reconcile.object.lastHandledReconcileRequest()
|
||||
logger.Actionf("annotating %s %s in %s namespace", reconcile.kind, name, rootArgs.namespace)
|
||||
if err := requestReconciliation(ctx, kubeClient, namespacedName, reconcile.object); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Successf("%s annotated", reconcile.kind)
|
||||
|
||||
lastHandledReconcileAt := reconcile.object.lastHandledReconcileRequest()
|
||||
logger.Waitingf("waiting for %s reconciliation", reconcile.kind)
|
||||
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
|
||||
reconciliationHandled(ctx, kubeClient, namespacedName, reconcile.object, lastHandledReconcileAt)); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Successf("%s reconciliation completed", reconcile.kind)
|
||||
|
||||
if apimeta.IsStatusConditionFalse(*reconcile.object.GetStatusConditions(), meta.ReadyCondition) {
|
||||
return fmt.Errorf("%s reconciliation failed", reconcile.kind)
|
||||
readyCond := apimeta.FindStatusCondition(*reconcile.object.GetStatusConditions(), meta.ReadyCondition)
|
||||
if readyCond == nil {
|
||||
return fmt.Errorf("status can't be determined")
|
||||
}
|
||||
|
||||
if readyCond.Status != metav1.ConditionTrue {
|
||||
return fmt.Errorf("%s reconciliation failed: %s", reconcile.kind, readyCond.Message)
|
||||
}
|
||||
logger.Successf(reconcile.object.successMessage())
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var resumeKsCmd = &cobra.Command{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package main
|
|||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var suspendKsCmd = &cobra.Command{
|
||||
|
|
|
|||
3
cmd/flux/testdata/check/check_pre.golden
vendored
3
cmd/flux/testdata/check/check_pre.golden
vendored
|
|
@ -1,4 +1,3 @@
|
|||
► checking prerequisites
|
||||
✔ kubectl {{ .clientVersion }} >=1.18.0-0
|
||||
✔ Kubernetes {{ .serverVersion }} >=1.16.0-0
|
||||
✔ Kubernetes {{ .serverVersion }} >=1.19.0-0
|
||||
✔ prerequisites checks passed
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
► annotating GitRepository thrfg in {{ .ns }} namespace
|
||||
✔ GitRepository annotated
|
||||
◎ waiting for GitRepository reconciliation
|
||||
✔ GitRepository reconciliation completed
|
||||
✔ fetched revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951
|
||||
► annotating HelmRelease thrfg in {{ .ns }} namespace
|
||||
✔ HelmRelease annotated
|
||||
◎ waiting for HelmRelease reconciliation
|
||||
✔ HelmRelease reconciliation completed
|
||||
✔ applied revision 6.0.0
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
► annotating GitRepository tkfg in {{ .ns }} namespace
|
||||
✔ GitRepository annotated
|
||||
◎ waiting for GitRepository reconciliation
|
||||
✔ GitRepository reconciliation completed
|
||||
✔ fetched revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951
|
||||
► annotating Kustomization tkfg in {{ .ns }} namespace
|
||||
✔ Kustomization annotated
|
||||
◎ waiting for Kustomization reconciliation
|
||||
✔ Kustomization reconciliation completed
|
||||
✔ applied revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import (
|
|||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
fluxmeta "github.com/fluxcd/pkg/apis/meta"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import (
|
|||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,129 @@
|
|||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
)
|
||||
|
||||
func getVersion(input string) (string, error) {
|
||||
if input == "" {
|
||||
return rootArgs.defaults.Version, nil
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the client and server-side components version information.",
|
||||
Long: "Print the client and server-side components version information for the current context.",
|
||||
Example: `# Print client and server-side version
|
||||
flux version
|
||||
|
||||
# Print only client version
|
||||
flux version --client
|
||||
|
||||
# Print information in json format
|
||||
flux version -o json
|
||||
`,
|
||||
RunE: versionCmdRun,
|
||||
}
|
||||
|
||||
type versionFlags struct {
|
||||
client bool
|
||||
output string
|
||||
}
|
||||
|
||||
var versionArgs versionFlags
|
||||
|
||||
func init() {
|
||||
versionCmd.Flags().BoolVar(&versionArgs.client, "client", false,
|
||||
"print only client version")
|
||||
versionCmd.Flags().StringVarP(&versionArgs.output, "output", "o", "yaml",
|
||||
"the format in which the information should be printed. can be 'json' or 'yaml'")
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
||||
func versionCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if versionArgs.output != "yaml" && versionArgs.output != "json" {
|
||||
return fmt.Errorf("--output must be json or yaml, not %s", versionArgs.output)
|
||||
}
|
||||
|
||||
if isEmbeddedVersion(input) {
|
||||
return input, nil
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
var err error
|
||||
if input == install.MakeDefaultOptions().Version {
|
||||
input, err = install.GetLatestVersion()
|
||||
info := map[string]string{}
|
||||
info["flux"] = rootArgs.defaults.Version
|
||||
|
||||
if !versionArgs.client {
|
||||
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if ok, err := install.ExistingVersion(input); err != nil || !ok {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("targeted version '%s' does not exist", input)
|
||||
|
||||
selector := client.MatchingLabels{"app.kubernetes.io/instance": rootArgs.namespace}
|
||||
var list v1.DeploymentList
|
||||
if err := kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace), selector); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(list.Items) == 0 {
|
||||
return fmt.Errorf("no deployments found in %s namespace", rootArgs.namespace)
|
||||
}
|
||||
|
||||
for _, d := range list.Items {
|
||||
for _, c := range d.Spec.Template.Spec.Containers {
|
||||
name, tag, err := splitImageStr(c.Image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info[name] = tag
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if !utils.CompatibleVersion(VERSION, input) {
|
||||
return "", fmt.Errorf("targeted version '%s' is not compatible with your current version of flux (%s)", input, VERSION)
|
||||
var marshalled []byte
|
||||
var err error
|
||||
|
||||
if versionArgs.output == "json" {
|
||||
marshalled, err = json.MarshalIndent(&info, "", " ")
|
||||
marshalled = append(marshalled, "\n"...)
|
||||
} else {
|
||||
marshalled, err = yaml.Marshal(&info)
|
||||
}
|
||||
return input, nil
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rootCmd.Print(string(marshalled))
|
||||
return nil
|
||||
}
|
||||
|
||||
func isEmbeddedVersion(input string) bool {
|
||||
return input == rootArgs.defaults.Version
|
||||
func splitImageStr(image string) (string, string, error) {
|
||||
imageArr := strings.Split(image, ":")
|
||||
if len(imageArr) < 2 {
|
||||
return "", "", fmt.Errorf("missing image tag in image %s", image)
|
||||
}
|
||||
|
||||
name, tag := imageArr[0], imageArr[1]
|
||||
nameArr := strings.Split(name, "/")
|
||||
return nameArr[len(nameArr)-1], tag, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
// +build unit
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "--version",
|
||||
assert: assertGoldenValue("flux version 0.0.0-dev.0\n"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
58
cmd/flux/version_utils.go
Normal file
58
cmd/flux/version_utils.go
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright 2020 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
)
|
||||
|
||||
func getVersion(input string) (string, error) {
|
||||
if input == "" {
|
||||
return rootArgs.defaults.Version, nil
|
||||
}
|
||||
|
||||
if isEmbeddedVersion(input) {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
if input == install.MakeDefaultOptions().Version {
|
||||
input, err = install.GetLatestVersion()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
if ok, err := install.ExistingVersion(input); err != nil || !ok {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("targeted version '%s' does not exist", input)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if !utils.CompatibleVersion(VERSION, input) {
|
||||
return "", fmt.Errorf("targeted version '%s' is not compatible with your current version of flux (%s)", input, VERSION)
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func isEmbeddedVersion(input string) bool {
|
||||
return input == rootArgs.defaults.Version
|
||||
}
|
||||
55
cmd/flux/version_utils_test.go
Normal file
55
cmd/flux/version_utils_test.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// +build unit
|
||||
|
||||
/*
|
||||
Copyright 2021 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "--version",
|
||||
assert: assertGoldenValue("flux version 0.0.0-dev.0\n"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestVersionCmd(t *testing.T) {
|
||||
tests := []struct {
|
||||
args string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
args: "version --client",
|
||||
expected: "flux: v0.0.0-dev.0\n",
|
||||
},
|
||||
{
|
||||
args: "version --client -o json",
|
||||
expected: "{\n \"flux\": \"v0.0.0-dev.0\"\n}\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
cmd := cmdTestCase{
|
||||
args: tt.args,
|
||||
assert: assertGoldenValue(tt.expected),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
}
|
||||
28
go.mod
28
go.mod
|
|
@ -4,21 +4,23 @@ go 1.16
|
|||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.1.0
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/fluxcd/go-git-providers v0.1.1
|
||||
github.com/fluxcd/helm-controller/api v0.11.2
|
||||
github.com/fluxcd/image-automation-controller/api v0.14.1
|
||||
github.com/fluxcd/image-reflector-controller/api v0.11.1
|
||||
github.com/fluxcd/kustomize-controller/api v0.14.1
|
||||
github.com/fluxcd/notification-controller/api v0.16.0
|
||||
github.com/fluxcd/helm-controller/api v0.12.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.12.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.15.2
|
||||
github.com/fluxcd/notification-controller/api v0.17.0
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.0
|
||||
github.com/fluxcd/pkg/runtime v0.12.0
|
||||
github.com/fluxcd/pkg/ssa v0.0.3
|
||||
github.com/fluxcd/pkg/ssh v0.0.5
|
||||
github.com/fluxcd/pkg/untar v0.0.5
|
||||
github.com/fluxcd/pkg/version v0.0.1
|
||||
github.com/fluxcd/source-controller/api v0.15.4
|
||||
github.com/fluxcd/source-controller/api v0.16.0
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/google/go-cmp v0.5.5
|
||||
github.com/google/go-cmp v0.5.6
|
||||
github.com/google/go-containerregistry v0.2.0
|
||||
github.com/manifoldco/promptui v0.7.0
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
|
|
@ -26,15 +28,15 @@ require (
|
|||
github.com/spf13/cobra v1.1.3
|
||||
github.com/spf13/pflag v1.0.5
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
|
||||
k8s.io/api v0.21.3
|
||||
k8s.io/apiextensions-apiserver v0.21.3
|
||||
k8s.io/apimachinery v0.21.3
|
||||
k8s.io/client-go v0.21.3
|
||||
k8s.io/api v0.22.2
|
||||
k8s.io/apiextensions-apiserver v0.22.2
|
||||
k8s.io/apimachinery v0.22.2
|
||||
k8s.io/client-go v0.22.2
|
||||
k8s.io/kubectl v0.21.1
|
||||
sigs.k8s.io/cli-utils v0.25.1-0.20210608181808-f3974341173a
|
||||
sigs.k8s.io/controller-runtime v0.9.5
|
||||
sigs.k8s.io/controller-runtime v0.10.1
|
||||
sigs.k8s.io/kustomize/api v0.8.10
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
// drop LGPL dependency manifoldco/promptui -> juju/ansiterm
|
||||
|
|
|
|||
173
go.sum
173
go.sum
|
|
@ -28,18 +28,22 @@ github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
|
|||
github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go v42.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
|
||||
github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
|
||||
github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE=
|
||||
github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
|
||||
github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
|
||||
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
|
|
@ -54,8 +58,9 @@ github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsI
|
|||
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
|
||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
|
||||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
|
|
@ -96,6 +101,7 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5
|
|||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
|
|
@ -112,6 +118,7 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
|
|||
github.com/aws/aws-sdk-go v1.28.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
|
|
@ -124,6 +131,8 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
|
|||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
|
|
@ -138,7 +147,11 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
|||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
||||
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
|
|
@ -149,6 +162,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
|
|
@ -193,6 +207,8 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
|
|||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc=
|
||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||
|
|
@ -203,18 +219,19 @@ github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL
|
|||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fluxcd/go-git-providers v0.1.1 h1:R4VafMOo1IlfEZcImApCeElge/HajhFvRzDKGlot+/c=
|
||||
github.com/fluxcd/go-git-providers v0.1.1/go.mod h1:nRgNpHZmZhrsyNSma1JcAhjUG9xrqMGJcIUr9K7M7vk=
|
||||
github.com/fluxcd/helm-controller/api v0.11.2 h1:IpzGEexjEa9DttikHF40kHFORhsxAeD2Z6SN6BZBA6o=
|
||||
github.com/fluxcd/helm-controller/api v0.11.2/go.mod h1:gLPpLa8NMQJ+b4pwP/sExAPkGdFWO1CKIh1Uu82O2gM=
|
||||
github.com/fluxcd/image-automation-controller/api v0.14.1 h1:8EDUs61Gi5HgSA9ou0rgFuDgvag+wpTrndizFhCGYwY=
|
||||
github.com/fluxcd/image-automation-controller/api v0.14.1/go.mod h1:22GZblh0CmaZItQpvCBe40i5ql/oCZllpLqkGmoglEQ=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.11.1 h1:8pmUKL7Pise0JOBFgqw7eWtOK/rs3HNibXqCK9aJ8LE=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.11.1/go.mod h1:lgQHGFz29OHmDU5Jwg689C/M+P/f9ujt6NS0zCLT0BQ=
|
||||
github.com/fluxcd/kustomize-controller/api v0.14.1 h1:OsErJQ3U3ReYTAtkeFo1t8UW4sjISF0a+6wsz942MT0=
|
||||
github.com/fluxcd/kustomize-controller/api v0.14.1/go.mod h1:3RNiEd/XnYjSTGzMqDzDbQkOYpdPFrKuS+XdgWt9pds=
|
||||
github.com/fluxcd/notification-controller/api v0.16.0 h1:3vaIj3AJRUA4dsfISuok8URV1RUmoe9NFpCAZ+tjOeU=
|
||||
github.com/fluxcd/notification-controller/api v0.16.0/go.mod h1:t28GMWMLiLqho+ikpZrldv22/vmCsFdQR8vdJluxknc=
|
||||
github.com/fluxcd/helm-controller/api v0.12.0 h1:68GKGZ5dHvOt4rx6gwQaOGliUksv7F/q8JQo2c0Tcis=
|
||||
github.com/fluxcd/helm-controller/api v0.12.0/go.mod h1:zWmzV0s2SU4rEIGLPTt+dsaMs40OsNQgSgOATgJmxB0=
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0 h1:KI350vt5JahE43D17VyLZFH4ZxtbnyHrekAd8AJsT5E=
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0/go.mod h1:XvrEEpM1rVU+x1gQeXB/dj56w1dmOJRraTxQWOiuNME=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.12.0 h1:ghdbOUmbNaPi/jVfNnI3xzvhudXBZx6xUld/OLNSVXM=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.12.0/go.mod h1:lgQHGFz29OHmDU5Jwg689C/M+P/f9ujt6NS0zCLT0BQ=
|
||||
github.com/fluxcd/kustomize-controller/api v0.15.2 h1:6MEt9ke7eQeRZsFPv+OzPeXuURS9axCIFgV3KopDOmo=
|
||||
github.com/fluxcd/kustomize-controller/api v0.15.2/go.mod h1:OhnZuXBeDl4NqbDZgpYKRg8nmsmeUIddH3vX8wxym9A=
|
||||
github.com/fluxcd/notification-controller/api v0.17.0 h1:HrTX6EThmvbW3I+uKJyaggcNnRsLxogc6q7A3nXZ9tQ=
|
||||
github.com/fluxcd/notification-controller/api v0.17.0/go.mod h1:t28GMWMLiLqho+ikpZrldv22/vmCsFdQR8vdJluxknc=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.1.0/go.mod h1:gEl+W5cVykCC3RfrCaqe+Pz+j4lKl2aeR4dxsom/zII=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.2.0 h1:jhu2QHvs+j3Zo9rR6w8hkO3LSC6h3M37zY5ejufOmxY=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.2.0/go.mod h1:gEl+W5cVykCC3RfrCaqe+Pz+j4lKl2aeR4dxsom/zII=
|
||||
|
|
@ -222,23 +239,27 @@ github.com/fluxcd/pkg/apis/meta v0.10.0 h1:N7wVGHC1cyPdT87hrDC7UwCwRwnZdQM46PBSL
|
|||
github.com/fluxcd/pkg/apis/meta v0.10.0/go.mod h1:CW9X9ijMTpNe7BwnokiUOrLl/h13miwVr/3abEQLbKE=
|
||||
github.com/fluxcd/pkg/runtime v0.12.0 h1:BPZZ8bBkimpqGAPXqOf3LTaw+tcw6HgbWyCuzbbsJGs=
|
||||
github.com/fluxcd/pkg/runtime v0.12.0/go.mod h1:EyaTR2TOYcjL5U//C4yH3bt2tvTgIOSXpVRbWxUn/C4=
|
||||
github.com/fluxcd/pkg/ssa v0.0.3 h1:5s/dZIaJGtI/46w5VRmr5sy/jNJGpxPnSad8oSzAbkc=
|
||||
github.com/fluxcd/pkg/ssa v0.0.3/go.mod h1:B/6V2gF3zq3P6EstM/qTmOEUf3YgOh1ybFfAAmG4Shw=
|
||||
github.com/fluxcd/pkg/ssh v0.0.5 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A=
|
||||
github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs=
|
||||
github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk=
|
||||
github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw=
|
||||
github.com/fluxcd/pkg/version v0.0.1 h1:/8asQoDXSThz3csiwi4Qo8Zb6blAxLXbtxNgeMJ9bCg=
|
||||
github.com/fluxcd/pkg/version v0.0.1/go.mod h1:WAF4FEEA9xyhngF8TDxg3UPu5fA1qhEYV8Pmi2Il01Q=
|
||||
github.com/fluxcd/source-controller/api v0.15.4 h1:9aRcH/WKJWt7Bp954K/wzLRuiRiHuD2osvYp74GoP64=
|
||||
github.com/fluxcd/source-controller/api v0.15.4/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/fluxcd/source-controller/api v0.16.0 h1:xFz+K7lLg/82uOQp+a0g04GsgoWNfyzwXAoVQy4T/oI=
|
||||
github.com/fluxcd/source-controller/api v0.16.0/go.mod h1:guUCCapjzE2kocwFreQTM/IGvtAglIJc4L97mokairo=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
|
|
@ -285,14 +306,16 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+
|
|||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||
github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
|
||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
|
|
@ -316,8 +339,9 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
|
|||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
|
||||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
|
||||
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
|
||||
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
|
||||
|
|
@ -326,6 +350,7 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
|||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
|
|
@ -339,8 +364,9 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er
|
|||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
|
|
@ -363,12 +389,14 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
|||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
|
|
@ -377,8 +405,9 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-containerregistry v0.2.0 h1:cWFYx+kOkKdyOET0pcp7GMCmxj7da40StvluSuSXWCg=
|
||||
github.com/google/go-containerregistry v0.2.0/go.mod h1:Ts3Wioz1r5ayWx8sS6vLcWltWcM1aqFjd/eVrkFhrWM=
|
||||
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
|
||||
|
|
@ -426,9 +455,11 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJr
|
|||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
|
|
@ -454,7 +485,6 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
|
|||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
|
|
@ -478,6 +508,9 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
|
|||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
|
|
@ -525,8 +558,9 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN
|
|||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
|
||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
|
|
@ -556,6 +590,7 @@ github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:F
|
|||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
@ -610,8 +645,9 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
|
|||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.12.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||
github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI=
|
||||
github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||
github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU=
|
||||
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
|
|
@ -680,6 +716,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
|
|||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
|
|
@ -701,9 +738,11 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
|
|||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
|
|
@ -742,6 +781,7 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
|
|||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
|
|
@ -758,11 +798,20 @@ github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6Ut
|
|||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
|
||||
go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc=
|
||||
go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4=
|
||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
|
|
@ -772,6 +821,18 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
|||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
|
||||
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
|
||||
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
|
||||
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
|
||||
go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
|
||||
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
|
||||
go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
|
||||
go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
|
||||
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
|
|
@ -791,8 +852,9 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
|||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4=
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
|
||||
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
|
@ -837,6 +899,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
|||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
|
|
@ -846,6 +909,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
|||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -887,11 +951,14 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
|||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
|
@ -910,6 +977,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -959,6 +1027,7 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -968,12 +1037,17 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo=
|
||||
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
|
|
@ -985,6 +1059,7 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
|||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
@ -1049,6 +1124,7 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X
|
|||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
@ -1102,11 +1178,14 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4
|
|||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
|
|
@ -1121,6 +1200,10 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
|
@ -1160,6 +1243,7 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
|
|||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
@ -1184,32 +1268,46 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
|
|||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
|
||||
k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s=
|
||||
k8s.io/api v0.21.3 h1:cblWILbLO8ar+Fj6xdDGr603HRsf8Wu9E9rngJeprZQ=
|
||||
k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg=
|
||||
k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY=
|
||||
k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw=
|
||||
k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8=
|
||||
k8s.io/apiextensions-apiserver v0.21.1/go.mod h1:KESQFCGjqVcVsZ9g0xX5bacMjyX5emuWcS2arzdEouA=
|
||||
k8s.io/apiextensions-apiserver v0.21.3 h1:+B6biyUWpqt41kz5x6peIsljlsuwvNAp/oFax/j2/aY=
|
||||
k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE=
|
||||
k8s.io/apiextensions-apiserver v0.22.1/go.mod h1:HeGmorjtRmRLE+Q8dJu6AYRoZccvCMsghwS8XTUYb2c=
|
||||
k8s.io/apiextensions-apiserver v0.22.2 h1:zK7qI8Ery7j2CaN23UCFaC1hj7dMiI87n01+nKuewd4=
|
||||
k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA=
|
||||
k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
|
||||
k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
|
||||
k8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII=
|
||||
k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI=
|
||||
k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||
k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk=
|
||||
k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||
k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
|
||||
k8s.io/apiserver v0.21.1/go.mod h1:nLLYZvMWn35glJ4/FZRhzLG/3MPxAaZTgV4FJZdr+tY=
|
||||
k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU=
|
||||
k8s.io/apiserver v0.22.1/go.mod h1:2mcM6dzSt+XndzVQJX21Gx0/Klo7Aen7i0Ai6tIa400=
|
||||
k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI=
|
||||
k8s.io/cli-runtime v0.21.1 h1:Oj/iZxa7LLXrhzShaLNF4rFJEIEBTDHj0dJw4ra2vX4=
|
||||
k8s.io/cli-runtime v0.21.1/go.mod h1:TI9Bvl8lQWZB2KqE91QLCp9AZE4l29zNFnj/x4IX4Fw=
|
||||
k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
|
||||
k8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs=
|
||||
k8s.io/client-go v0.21.3 h1:J9nxZTOmvkInRDCzcSNQmPJbDYN/PjlxXT9Mos3HcLg=
|
||||
k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU=
|
||||
k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk=
|
||||
k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc=
|
||||
k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U=
|
||||
k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs=
|
||||
k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
|
||||
k8s.io/code-generator v0.21.1/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q=
|
||||
k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo=
|
||||
k8s.io/code-generator v0.22.1/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
|
||||
k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
|
||||
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
|
||||
k8s.io/component-base v0.21.1/go.mod h1:NgzFZ2qu4m1juby4TnrmpR8adRk6ka62YdH5DkIIyKA=
|
||||
k8s.io/component-base v0.21.3 h1:4WuuXY3Npa+iFfi2aDRiOz+anhNvRfye0859ZgfC5Og=
|
||||
k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ=
|
||||
k8s.io/component-base v0.22.1/go.mod h1:0D+Bl8rrnsPN9v0dyYvkqFfBeAd4u7n77ze+p8CMiPo=
|
||||
k8s.io/component-base v0.22.2 h1:vNIvE0AIrLhjX8drH0BgCNJcR4QZxMXcJzBsDplDx9M=
|
||||
k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug=
|
||||
k8s.io/component-helpers v0.21.1/go.mod h1:FtC1flbiQlosHQrLrRUulnKxE4ajgWCGy/67fT2GRlQ=
|
||||
k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
|
|
@ -1238,8 +1336,10 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
|||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210517184530-5a248b5acedc/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210527160623-6fdb442a123b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471 h1:DnzUXII7sVg1FJ/4JX6YDRJfLNAC7idRatPwe07suiI=
|
||||
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||
|
|
@ -1251,12 +1351,14 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
|||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
sigs.k8s.io/cli-utils v0.25.1-0.20210608181808-f3974341173a h1:S17+FPWGsOonXim+GcadLcSblEwL131Y9fKLfifSYkY=
|
||||
sigs.k8s.io/cli-utils v0.25.1-0.20210608181808-f3974341173a/go.mod h1:I4jgHr6uRfX0CkOMECwSgg2J48rNzZE1+kDXj9SnJBc=
|
||||
sigs.k8s.io/controller-runtime v0.9.0-beta.5.0.20210524185538-7181f1162e79/go.mod h1:rgf+cBz72pYlKXDRNhI1WFQv/S86EMUV4/ySmsEYgHk=
|
||||
sigs.k8s.io/controller-runtime v0.9.0/go.mod h1:TgkfvrhhEw3PlI0BRL/5xM+89y3/yc0ZDfdbTl84si8=
|
||||
sigs.k8s.io/controller-runtime v0.9.5 h1:WThcFE6cqctTn2jCZprLICO6BaKZfhsT37uAapTNfxc=
|
||||
sigs.k8s.io/controller-runtime v0.9.5/go.mod h1:q6PpkM5vqQubEKUKOM6qr06oXGzOBcCby1DA9FbyZeA=
|
||||
sigs.k8s.io/controller-runtime v0.10.1 h1:+eLHgY/VrJWnfg6iXUqhCUqNXgPH1NZeP9drNAAgWlg=
|
||||
sigs.k8s.io/controller-runtime v0.10.1/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY=
|
||||
sigs.k8s.io/kustomize/api v0.8.8/go.mod h1:He1zoK0nk43Pc6NlV085xDXDXTNprtcyKZVm3swsdNY=
|
||||
sigs.k8s.io/kustomize/api v0.8.10 h1:CqbdK/qT7JE+uVETkrVMk7pQf0fPFXk9+QQ//Q7sAtc=
|
||||
sigs.k8s.io/kustomize/api v0.8.10/go.mod h1:ImeIkhUU7GIhamOtKPlkllt+fkBKL5f6/4NLhVwkinA=
|
||||
|
|
@ -1274,6 +1376,7 @@ sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
|||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import (
|
|||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/bootstrap/git"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
|
|
@ -53,6 +53,10 @@ type PlainGitBootstrapper struct {
|
|||
author git.Author
|
||||
commitMessageAppendix string
|
||||
|
||||
gpgKeyRingPath string
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
|
||||
kubeconfig string
|
||||
kubecontext string
|
||||
|
||||
|
|
@ -142,6 +146,7 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
|||
}
|
||||
|
||||
// Git commit generated
|
||||
gpgOpts := git.WithGpgSigningOption(b.gpgKeyRingPath, b.gpgPassphrase, b.gpgKeyID)
|
||||
commitMsg := fmt.Sprintf("Add Flux %s component manifests", options.Version)
|
||||
if b.commitMessageAppendix != "" {
|
||||
commitMsg = commitMsg + "\n\n" + b.commitMessageAppendix
|
||||
|
|
@ -149,7 +154,7 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
|||
commit, err := b.git.Commit(git.Commit{
|
||||
Author: b.author,
|
||||
Message: commitMsg,
|
||||
})
|
||||
}, gpgOpts)
|
||||
if err != nil && err != git.ErrNoStagedFiles {
|
||||
return fmt.Errorf("failed to commit sync manifests: %w", err)
|
||||
}
|
||||
|
|
@ -170,41 +175,14 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
|||
// Apply components using any existing customisations
|
||||
kfile := filepath.Join(filepath.Dir(componentsYAML), konfig.DefaultKustomizationFileName())
|
||||
if _, err := os.Stat(kfile); err == nil {
|
||||
tmpDir, err := os.MkdirTemp("", "gotk-crds")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Extract the CRDs from the components manifest
|
||||
crdsYAML := filepath.Join(tmpDir, "gotk-crds.yaml")
|
||||
if err := utils.ExtractCRDs(componentsYAML, crdsYAML); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Apply the CRDs
|
||||
b.logger.Actionf("installing toolkit.fluxcd.io CRDs")
|
||||
kubectlArgs := []string{"apply", "-f", crdsYAML}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for CRDs to be established
|
||||
b.logger.Waitingf("waiting for CRDs to be reconciled")
|
||||
kubectlArgs = []string{"wait", "--for", "condition=established", "-f", crdsYAML}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
return err
|
||||
}
|
||||
b.logger.Successf("CRDs reconciled successfully")
|
||||
|
||||
// Apply the components and their patches
|
||||
b.logger.Actionf("installing components in %q namespace", options.Namespace)
|
||||
kubectlArgs = []string{"apply", "-k", filepath.Dir(componentsYAML)}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
if _, err := utils.Apply(ctx, b.kubeconfig, b.kubecontext, kfile); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Apply the CRDs and controllers
|
||||
b.logger.Actionf("installing components in %q namespace", options.Namespace)
|
||||
kubectlArgs := []string{"apply", "-f", componentsYAML}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
if _, err := utils.Apply(ctx, b.kubeconfig, b.kubecontext, componentsYAML); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -306,6 +284,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
|||
b.logger.Successf("generated sync manifests")
|
||||
|
||||
// Git commit generated
|
||||
gpgOpts := git.WithGpgSigningOption(b.gpgKeyRingPath, b.gpgPassphrase, b.gpgKeyID)
|
||||
commitMsg := fmt.Sprintf("Add Flux sync manifests")
|
||||
if b.commitMessageAppendix != "" {
|
||||
commitMsg = commitMsg + "\n\n" + b.commitMessageAppendix
|
||||
|
|
@ -313,7 +292,8 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
|||
commit, err := b.git.Commit(git.Commit{
|
||||
Author: b.author,
|
||||
Message: commitMsg,
|
||||
})
|
||||
}, gpgOpts)
|
||||
|
||||
if err != nil && err != git.ErrNoStagedFiles {
|
||||
return fmt.Errorf("failed to commit sync manifests: %w", err)
|
||||
}
|
||||
|
|
@ -329,10 +309,10 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
|||
|
||||
// Apply to cluster
|
||||
b.logger.Actionf("applying sync manifests")
|
||||
kubectlArgs := []string{"apply", "-k", filepath.Join(b.git.Path(), filepath.Dir(kusManifests.Path))}
|
||||
if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil {
|
||||
if _, err := utils.Apply(ctx, b.kubeconfig, b.kubecontext, filepath.Join(b.git.Path(), kusManifests.Path)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.logger.Successf("reconciled sync configuration")
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -318,6 +318,10 @@ func (b *GitProviderBootstrapper) reconcileOrgRepository(ctx context.Context) (g
|
|||
b.logger.Actionf("reconciling repository permissions")
|
||||
for _, i := range teamAccessInfo {
|
||||
var err error
|
||||
// Don't reconcile team if team already exists and b.reconcile is false
|
||||
if team, err := repo.TeamAccess().Get(ctx, i.Name); err == nil && !b.reconcile && team != nil {
|
||||
continue
|
||||
}
|
||||
_, changed, err = repo.TeamAccess().Reconcile(ctx, i)
|
||||
if err != nil {
|
||||
warning = fmt.Errorf("failed to grant permissions to team: %w", ErrReconciledWithWarning)
|
||||
|
|
|
|||
42
internal/bootstrap/git/commit_options.go
Normal file
42
internal/bootstrap/git/commit_options.go
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package git
|
||||
|
||||
// Option is a some configuration that modifies options for a commit.
|
||||
type Option interface {
|
||||
// ApplyToCommit applies this configuration to a given commit option.
|
||||
ApplyToCommit(*CommitOptions)
|
||||
}
|
||||
|
||||
// CommitOptions contains options for making a commit.
|
||||
type CommitOptions struct {
|
||||
*GPGSigningInfo
|
||||
}
|
||||
|
||||
// GPGSigningInfo contains information for signing a commit.
|
||||
type GPGSigningInfo struct {
|
||||
KeyRingPath string
|
||||
Passphrase string
|
||||
KeyID string
|
||||
}
|
||||
|
||||
type GpgSigningOption struct {
|
||||
*GPGSigningInfo
|
||||
}
|
||||
|
||||
func (w GpgSigningOption) ApplyToCommit(in *CommitOptions) {
|
||||
in.GPGSigningInfo = w.GPGSigningInfo
|
||||
}
|
||||
|
||||
func WithGpgSigningOption(path, passphrase, keyID string) Option {
|
||||
// Return nil if no path is set, even if other options are configured.
|
||||
if path == "" {
|
||||
return GpgSigningOption{}
|
||||
}
|
||||
|
||||
return GpgSigningOption{
|
||||
GPGSigningInfo: &GPGSigningInfo{
|
||||
KeyRingPath: path,
|
||||
Passphrase: passphrase,
|
||||
KeyID: keyID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ type Git interface {
|
|||
Init(url, branch string) (bool, error)
|
||||
Clone(ctx context.Context, url, branch string, caBundle []byte) (bool, error)
|
||||
Write(path string, reader io.Reader) error
|
||||
Commit(message Commit) (string, error)
|
||||
Commit(message Commit, options ...Option) (string, error)
|
||||
Push(ctx context.Context, caBundle []byte) error
|
||||
Status() (bool, error)
|
||||
Head() (string, error)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
gogit "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
|
|
@ -40,6 +41,12 @@ type GoGit struct {
|
|||
repository *gogit.Repository
|
||||
}
|
||||
|
||||
type CommitOptions struct {
|
||||
GpgKeyPath string
|
||||
GpgKeyPassphrase string
|
||||
KeyID string
|
||||
}
|
||||
|
||||
func New(path string, auth transport.AuthMethod) *GoGit {
|
||||
return &GoGit{
|
||||
path: path,
|
||||
|
|
@ -127,7 +134,7 @@ func (g *GoGit) Write(path string, reader io.Reader) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (g *GoGit) Commit(message git.Commit) (string, error) {
|
||||
func (g *GoGit) Commit(message git.Commit, opts ...git.Option) (string, error) {
|
||||
if g.repository == nil {
|
||||
return "", git.ErrNoGitRepository
|
||||
}
|
||||
|
|
@ -142,6 +149,12 @@ func (g *GoGit) Commit(message git.Commit) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
// apply the options
|
||||
options := &git.CommitOptions{}
|
||||
for _, opt := range opts {
|
||||
opt.ApplyToCommit(options)
|
||||
}
|
||||
|
||||
// go-git has [a bug](https://github.com/go-git/go-git/issues/253)
|
||||
// whereby it thinks broken symlinks to absolute paths are
|
||||
// modified. There's no circumstance in which we want to commit a
|
||||
|
|
@ -173,13 +186,24 @@ func (g *GoGit) Commit(message git.Commit) (string, error) {
|
|||
return head.Hash().String(), git.ErrNoStagedFiles
|
||||
}
|
||||
|
||||
commit, err := wt.Commit(message.Message, &gogit.CommitOptions{
|
||||
commitOpts := &gogit.CommitOptions{
|
||||
Author: &object.Signature{
|
||||
Name: message.Name,
|
||||
Email: message.Email,
|
||||
When: time.Now(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if options.GPGSigningInfo != nil {
|
||||
entity, err := getOpenPgpEntity(*options.GPGSigningInfo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
commitOpts.SignKey = entity
|
||||
}
|
||||
|
||||
commit, err := wt.Commit(message.Message, commitOpts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -232,3 +256,41 @@ func (g *GoGit) Path() string {
|
|||
func isRemoteBranchNotFoundErr(err error, ref string) bool {
|
||||
return strings.Contains(err.Error(), fmt.Sprintf("couldn't find remote ref %q", ref))
|
||||
}
|
||||
|
||||
func getOpenPgpEntity(info git.GPGSigningInfo) (*openpgp.Entity, error) {
|
||||
r, err := os.Open(info.KeyRingPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open GPG key ring: %w", err)
|
||||
}
|
||||
|
||||
entityList, err := openpgp.ReadKeyRing(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(entityList) == 0 {
|
||||
return nil, fmt.Errorf("empty GPG key ring")
|
||||
}
|
||||
|
||||
var entity *openpgp.Entity
|
||||
if info.KeyID != "" {
|
||||
for _, ent := range entityList {
|
||||
if ent.PrimaryKey.KeyIdString() == info.KeyID {
|
||||
entity = ent
|
||||
}
|
||||
}
|
||||
|
||||
if entity == nil {
|
||||
return nil, fmt.Errorf("no GPG private key matching key id '%s' found", info.KeyID)
|
||||
}
|
||||
} else {
|
||||
entity = entityList[0]
|
||||
}
|
||||
|
||||
err = entity.PrivateKey.Decrypt([]byte(info.Passphrase))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decrypt GPG private key: %w", err)
|
||||
}
|
||||
|
||||
return entity, nil
|
||||
}
|
||||
|
|
|
|||
66
internal/bootstrap/git/gogit/gogit_test.go
Normal file
66
internal/bootstrap/git/gogit/gogit_test.go
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// +build unit
|
||||
|
||||
package gogit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/bootstrap/git"
|
||||
)
|
||||
|
||||
func TestGetOpenPgpEntity(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
keyPath string
|
||||
passphrase string
|
||||
id string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "no default key id given",
|
||||
keyPath: "testdata/private.key",
|
||||
passphrase: "flux",
|
||||
id: "",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "key id given",
|
||||
keyPath: "testdata/private.key",
|
||||
passphrase: "flux",
|
||||
id: "0619327DBD777415",
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "wrong key id",
|
||||
keyPath: "testdata/private.key",
|
||||
passphrase: "flux",
|
||||
id: "0619327DBD777416",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "wrong password",
|
||||
keyPath: "testdata/private.key",
|
||||
passphrase: "fluxe",
|
||||
id: "0619327DBD777415",
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gpgInfo := git.GPGSigningInfo{
|
||||
KeyRingPath: tt.keyPath,
|
||||
Passphrase: tt.passphrase,
|
||||
KeyID: tt.id,
|
||||
}
|
||||
|
||||
_, err := getOpenPgpEntity(gpgInfo)
|
||||
if err != nil && !tt.expectErr {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
if err == nil && tt.expectErr {
|
||||
t.Errorf("expected error when %s", tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
BIN
internal/bootstrap/git/gogit/testdata/private.key
vendored
Normal file
BIN
internal/bootstrap/git/gogit/testdata/private.key
vendored
Normal file
Binary file not shown.
|
|
@ -112,3 +112,27 @@ func (o loggerOption) applyGit(b *PlainGitBootstrapper) {
|
|||
func (o loggerOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
b.logger = o.logger
|
||||
}
|
||||
|
||||
func WithGitCommitSigning(path, passphrase, keyID string) Option {
|
||||
return gitCommitSigningOption{
|
||||
gpgKeyRingPath: path,
|
||||
gpgPassphrase: passphrase,
|
||||
gpgKeyID: keyID,
|
||||
}
|
||||
}
|
||||
|
||||
type gitCommitSigningOption struct {
|
||||
gpgKeyRingPath string
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
}
|
||||
|
||||
func (o gitCommitSigningOption) applyGit(b *PlainGitBootstrapper) {
|
||||
b.gpgKeyRingPath = o.gpgKeyRingPath
|
||||
b.gpgPassphrase = o.gpgPassphrase
|
||||
b.gpgKeyID = o.gpgKeyID
|
||||
}
|
||||
|
||||
func (o gitCommitSigningOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
o.applyGit(b.PlainGitBootstrapper)
|
||||
}
|
||||
|
|
|
|||
85
internal/utils/apply.go
Normal file
85
internal/utils/apply.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/kustomization"
|
||||
)
|
||||
|
||||
// Apply is the equivalent of 'kubectl apply --server-side -f'.
|
||||
// If the given manifest is a kustomization.yaml, then apply performs the equivalent of 'kubectl apply --server-side -k'.
|
||||
func Apply(ctx context.Context, kubeConfigPath string, kubeContext string, manifestPath string) (string, error) {
|
||||
cfg, err := KubeConfig(kubeConfigPath, kubeContext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
restMapper, err := apiutil.NewDynamicRESTMapper(cfg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
kubeClient, err := client.New(cfg, client.Options{Mapper: restMapper})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
kubePoller := polling.NewStatusPoller(kubeClient, restMapper)
|
||||
|
||||
resourceManager := ssa.NewResourceManager(kubeClient, kubePoller, ssa.Owner{
|
||||
Field: "flux",
|
||||
Group: "fluxcd.io",
|
||||
})
|
||||
|
||||
objs, err := readObjects(manifestPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(objs) < 1 {
|
||||
return "", fmt.Errorf("no Kubernetes objects found at: %s", manifestPath)
|
||||
}
|
||||
|
||||
if err := ssa.SetNativeKindsDefaults(objs); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
changeSet, err := resourceManager.ApplyAllStaged(ctx, objs, false, time.Minute)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return changeSet.String(), nil
|
||||
}
|
||||
|
||||
func readObjects(manifestPath string) ([]*unstructured.Unstructured, error) {
|
||||
if _, err := os.Stat(manifestPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if filepath.Base(manifestPath) == konfig.DefaultKustomizationFileName() {
|
||||
resources, err := kustomization.Build(filepath.Dir(manifestPath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ssa.ReadObjects(bytes.NewReader(resources))
|
||||
}
|
||||
|
||||
ms, err := os.Open(manifestPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer ms.Close()
|
||||
|
||||
return ssa.ReadObjects(bufio.NewReader(ms))
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ import (
|
|||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
imageautov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
imagereflectv1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
"github.com/fluxcd/pkg/runtime/dependency"
|
||||
"github.com/fluxcd/pkg/version"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.11.2/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.11.2/helm-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.12.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.12.0/helm-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.14.1/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.14.1/image-automation-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.15.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.15.0/image-automation-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.11.1/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.11.1/image-reflector-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.12.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.12.0/image-reflector-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.14.1/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.14.1/kustomize-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.15.2/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.15.2/kustomize-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.16.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.16.0/notification-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.17.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.17.0/notification-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.15.4/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.15.4/source-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.16.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.16.0/source-controller.deployment.yaml
|
||||
- account.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.15.4/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.14.1/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.11.2/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.16.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.11.1/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.14.1/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.16.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.15.2/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.12.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.17.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.12.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.15.0/image-automation-controller.crds.yaml
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ spec:
|
|||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- image: bitnami/kubectl
|
||||
- image: ghcr.io/fluxcd/flux-cli:v0.17.2
|
||||
securityContext:
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ spec:
|
|||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- image: bitnami/kubectl
|
||||
- image: ghcr.io/fluxcd/flux-cli:v0.17.2
|
||||
name: copy-kubectl
|
||||
# it's okay to do this because kubectl is a statically linked binary
|
||||
command:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ spec:
|
|||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- image: bitnami/kubectl
|
||||
- image: ghcr.io/fluxcd/flux-cli:v0.17.2
|
||||
name: copy-kubectl
|
||||
# it's okay to do this because kubectl is a statically linked binary
|
||||
command:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ spec:
|
|||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- image: bitnami/kubectl
|
||||
- image: ghcr.io/fluxcd/flux-cli:v0.17.2
|
||||
name: copy-kubectl
|
||||
# it's okay to do this because kubectl is a statically linked binary
|
||||
command:
|
||||
|
|
|
|||
|
|
@ -25,13 +25,11 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/api/krusty"
|
||||
kustypes "sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
"github.com/fluxcd/pkg/untar"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/kustomization"
|
||||
)
|
||||
|
||||
func fetch(ctx context.Context, url, version, dir string) error {
|
||||
|
|
@ -114,56 +112,13 @@ func generate(base string, options Options) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
var kustomizeBuildMutex sync.Mutex
|
||||
|
||||
func build(base, output string) error {
|
||||
// TODO(stefan): temporary workaround for concurrent map read and map write bug
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/3659
|
||||
kustomizeBuildMutex.Lock()
|
||||
defer kustomizeBuildMutex.Unlock()
|
||||
|
||||
kfile := filepath.Join(base, "kustomization.yaml")
|
||||
resources, err := kustomization.Build(base)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fs := filesys.MakeFsOnDisk()
|
||||
if !fs.Exists(kfile) {
|
||||
return fmt.Errorf("%s not found", kfile)
|
||||
}
|
||||
|
||||
// TODO(hidde): work around for a bug in kustomize causing it to
|
||||
// not properly handle absolute paths on Windows.
|
||||
// Convert the path to a relative path to the working directory
|
||||
// as a temporary fix:
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/2789
|
||||
if filepath.IsAbs(base) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
base, err = filepath.Rel(wd, base)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
buildOptions := &krusty.Options{
|
||||
DoLegacyResourceSort: true,
|
||||
LoadRestrictions: kustypes.LoadRestrictionsNone,
|
||||
AddManagedbyLabel: false,
|
||||
DoPrune: false,
|
||||
PluginConfig: kustypes.DisabledPluginConfig(),
|
||||
}
|
||||
|
||||
k := krusty.MakeKustomizer(buildOptions)
|
||||
m, err := k.Run(fs, base)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resources, err := m.AsYaml()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := fs.WriteFile(output, resources); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,14 @@ limitations under the License.
|
|||
package kustomization
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/api/krusty"
|
||||
"sigs.k8s.io/kustomize/api/provider"
|
||||
kustypes "sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
|
@ -28,6 +32,8 @@ import (
|
|||
"github.com/fluxcd/flux2/pkg/manifestgen"
|
||||
)
|
||||
|
||||
// Generate scans the given directory for Kubernetes manifests and creates a kustomization.yaml
|
||||
// including all discovered manifests as resources.
|
||||
func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
kfile := filepath.Join(options.TargetPath, konfig.DefaultKustomizationFileName())
|
||||
abskfile := filepath.Join(options.BaseDir, kfile)
|
||||
|
|
@ -121,3 +127,57 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
|||
Content: string(kd),
|
||||
}, nil
|
||||
}
|
||||
|
||||
var kustomizeBuildMutex sync.Mutex
|
||||
|
||||
// Build takes a Kustomize overlays and returns the resulting manifests as multi-doc YAML.
|
||||
func Build(base string) ([]byte, error) {
|
||||
// TODO(stefan): temporary workaround for concurrent map read and map write bug
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/3659
|
||||
kustomizeBuildMutex.Lock()
|
||||
defer kustomizeBuildMutex.Unlock()
|
||||
|
||||
kfile := filepath.Join(base, konfig.DefaultKustomizationFileName())
|
||||
|
||||
fs := filesys.MakeFsOnDisk()
|
||||
if !fs.Exists(kfile) {
|
||||
return nil, fmt.Errorf("%s not found", kfile)
|
||||
}
|
||||
|
||||
// TODO(hidde): work around for a bug in kustomize causing it to
|
||||
// not properly handle absolute paths on Windows.
|
||||
// Convert the path to a relative path to the working directory
|
||||
// as a temporary fix:
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/2789
|
||||
if filepath.IsAbs(base) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base, err = filepath.Rel(wd, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
buildOptions := &krusty.Options{
|
||||
DoLegacyResourceSort: true,
|
||||
LoadRestrictions: kustypes.LoadRestrictionsNone,
|
||||
AddManagedbyLabel: false,
|
||||
DoPrune: false,
|
||||
PluginConfig: kustypes.DisabledPluginConfig(),
|
||||
}
|
||||
|
||||
k := krusty.MakeKustomizer(buildOptions)
|
||||
m, err := k.Run(fs, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resources, err := m.AsYaml()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ type Options struct {
|
|||
Name string
|
||||
Namespace string
|
||||
Branch string
|
||||
Tag string
|
||||
SemVer string
|
||||
Commit string
|
||||
Secret string
|
||||
TargetPath string
|
||||
ManifestFile string
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
|
||||
|
|
@ -35,6 +35,20 @@ import (
|
|||
|
||||
func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
gvk := sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)
|
||||
gitRef := &sourcev1.GitRepositoryRef{}
|
||||
if options.Branch != "" {
|
||||
gitRef.Branch = options.Branch
|
||||
}
|
||||
if options.Tag != "" {
|
||||
gitRef.Tag = options.Tag
|
||||
}
|
||||
if options.SemVer != "" {
|
||||
gitRef.SemVer = options.SemVer
|
||||
}
|
||||
if options.Commit != "" {
|
||||
gitRef.Commit = options.Commit
|
||||
}
|
||||
|
||||
gitRepository := sourcev1.GitRepository{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: gvk.Kind,
|
||||
|
|
@ -49,9 +63,7 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
|||
Interval: metav1.Duration{
|
||||
Duration: options.Interval,
|
||||
},
|
||||
Reference: &sourcev1.GitRepositoryRef{
|
||||
Branch: options.Branch,
|
||||
},
|
||||
Reference: gitRef,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: options.Secret,
|
||||
},
|
||||
|
|
@ -85,7 +97,6 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
|||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: options.Name,
|
||||
},
|
||||
Validation: "client",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,11 @@ package sync
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
|
|
|
|||
40
tests/.gitignore
vendored
Normal file
40
tests/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/terraform
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=terraform
|
||||
|
||||
### Terraform ###
|
||||
# Local .terraform directories
|
||||
**/.terraform/*
|
||||
|
||||
# .tfstate files
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
|
||||
# Crash log files
|
||||
crash.log
|
||||
|
||||
# Exclude all .tfvars files, which are likely to contain sentitive data, such as
|
||||
# password, private keys, and other secrets. These should not be part of version
|
||||
# control as they are data points which are potentially sensitive and subject
|
||||
# to change depending on the environment.
|
||||
#
|
||||
*.tfvars
|
||||
|
||||
# Ignore override files as they are usually used to override resources locally and so
|
||||
# are not checked in
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
|
||||
# Include override files you do wish to add to version control using negated pattern
|
||||
# !example_override.tf
|
||||
|
||||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
|
||||
# example: *tfplan*
|
||||
|
||||
# Ignore CLI configuration files
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/terraform
|
||||
51
tests/azure/README.md
Normal file
51
tests/azure/README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Azure E2E
|
||||
|
||||
E2E tests for Azure are needed to mitigate introduction of new bugs in dependencies like libgit2. The goal is to verify that Flux integration with
|
||||
Azure services are actually working now and in the future.
|
||||
|
||||
## Architecture
|
||||
|
||||
The tests are run with the help of pre configured Azure subscriptions and Azure DevOps organization. Access to thse accounts are currently limited to
|
||||
Flux maintainers.
|
||||
* [Azure Subscription](https://portal.azure.com/#@weaveworksendtoend.onmicrosoft.com/resource/subscriptions/71e8dce4-9af6-405a-8e96-425f5d3c302b/overview)
|
||||
* [Azure DevOps organization](https://dev.azure.com/flux-azure/)
|
||||
|
||||
All infrastructure is and should be created with Terraform. There are two separate Terraform states. All state should be configured to use remote
|
||||
state in Azure. They should all be placed in the [same container](https://portal.azure.com/#@weaveworksendtoend.onmicrosoft.com/resource/subscriptions/71e8dce4-9af6-405a-8e96-425f5d3c302b/resourceGroups/terraform-state/providers/Microsoft.Storage/storageAccounts/terraformstate0419/containersList)
|
||||
but use different keys.
|
||||
|
||||
The [shared](./terraform/shared) Terraform creates long running cheaper infrastructure that is used across all tests. This includes a Key Vault which
|
||||
contains an ssh key and Azure DevOps Personal Access Token which cant be created automatically. It also includes an Azure Container Registry which the
|
||||
forked [podinfo](https://dev.azure.com/flux-azure/e2e/_git/podinfo) repository pushes an Helm Chart and Docker image to.
|
||||
|
||||
The [aks](./terraform/aks) Terraform creates the AKS cluster and related resources to run the tests. It creates the AKS cluster, Azure DevOps
|
||||
repositories, Key Vault Key for Sops, and Azure EventHub. The resources should be created and destroyed before and after every test run. Currently
|
||||
the same state is reused between runs to make sure that resources are left running after each test run.
|
||||
|
||||
## Tests
|
||||
|
||||
Each test run is intiated by running `terraform apply` on the aks Terraform, it does this by using the library [terraform-exec](github.com/hashicorp/terraform-exec).
|
||||
It then reads the output of the Terraform to get credentials and ssh keys, this means that a lot of the communication with the Azure API is offest to
|
||||
Terraform instead of requiring it to be implemented in the test.
|
||||
|
||||
The following tests are currently implemented:
|
||||
|
||||
- [x] Flux can be successfully installed on AKS using the CLI e.g.:
|
||||
- [x] source-controller can clone Azure DevOps repositories (https+ssh)
|
||||
- [x] image-reflector-controller can list tags from Azure Container Registry image repositories
|
||||
- [x] kustomize-controller can decrypt secrets using SOPS and Azure Key Vault
|
||||
- [x] image-automation-controller can create branches and push to Azure DevOps repositories (https+ssh)
|
||||
- [x] notification-controller can send commit status to Azure DevOps
|
||||
- [x] notification-controller can forward events to Azure Event Hub
|
||||
- [x] source-controller can pull charts from Azure Container Registry Helm repositories
|
||||
|
||||
## Give User Access
|
||||
|
||||
There are a couple of steps required when adding a new user to get access to the Azure portal and Azure DevOps. To begin with add the new user to
|
||||
[Azure AD](https://portal.azure.com/#blade/Microsoft_AAD_IAM/UsersManagementMenuBlade/MsGraphUsers), and add the user to the [Azure AD group
|
||||
flux-contributors](https://portal.azure.com/#blade/Microsoft_AAD_IAM/GroupDetailsMenuBlade/Overview/groupId/24e0f3f6-6555-4d3d-99ab-414c869cab5d). The
|
||||
new users should now go through the invite process, and be able to sign in to both the Azure Portal and Azure DevOps.
|
||||
|
||||
After the new user has signed into Azure DevOps you will need to modify the users permissions. This cannot be done before the user has signed in a
|
||||
first time. In the [organization users page](https://dev.azure.com/flux-azure/_settings/users) chose "Manage User" and set the "Access Level" to basic
|
||||
and make the user "Project Contributor" of the "e2e" Azure DevOps project.
|
||||
884
tests/azure/azure_test.go
Normal file
884
tests/azure/azure_test.go
Normal file
|
|
@ -0,0 +1,884 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
b64 "encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
eventhub "github.com/Azure/azure-event-hubs-go/v3"
|
||||
"github.com/hashicorp/terraform-exec/tfexec"
|
||||
"github.com/hashicorp/terraform-exec/tfinstall"
|
||||
git2go "github.com/libgit2/git2go/v31"
|
||||
"github.com/microsoft/azure-devops-go-api/azuredevops"
|
||||
"github.com/microsoft/azure-devops-go-api/azuredevops/git"
|
||||
"github.com/stretchr/testify/require"
|
||||
giturls "github.com/whilp/git-urls"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
automationv1beta1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
reflectorv1beta1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
notiv1beta1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/runtime/events"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
kubeconfigPath string
|
||||
kubeClient client.Client
|
||||
|
||||
azdoPat string
|
||||
idRsa string
|
||||
idRsaPub string
|
||||
knownHosts string
|
||||
fleetInfraRepository repoConfig
|
||||
applicationRepository repoConfig
|
||||
|
||||
fluxAzureSp spConfig
|
||||
sopsId string
|
||||
acr acrConfig
|
||||
eventHubSas string
|
||||
}
|
||||
|
||||
type spConfig struct {
|
||||
tenantId string
|
||||
clientId string
|
||||
clientSecret string
|
||||
}
|
||||
|
||||
type repoConfig struct {
|
||||
http string
|
||||
ssh string
|
||||
}
|
||||
|
||||
type acrConfig struct {
|
||||
url string
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
var cfg config
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
ctx := context.TODO()
|
||||
|
||||
log.Println("Setting up Azure test infrastructure")
|
||||
execPath, err := tfinstall.Find(ctx, &whichTerraform{})
|
||||
if err != nil {
|
||||
log.Fatalf("terraform exec path not found: %v", err)
|
||||
}
|
||||
tf, err := tfexec.NewTerraform("./terraform/aks", execPath)
|
||||
if err != nil {
|
||||
log.Fatalf("could not create terraform instance: %v", err)
|
||||
}
|
||||
log.Println("Init Terraform")
|
||||
err = tf.Init(ctx, tfexec.Upgrade(true))
|
||||
if err != nil {
|
||||
log.Fatalf("error running init: %v", err)
|
||||
}
|
||||
log.Println("Applying Terraform")
|
||||
err = tf.Apply(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("error running apply: %v", err)
|
||||
}
|
||||
state, err := tf.Show(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("error running show: %v", err)
|
||||
}
|
||||
outputs := state.Values.Outputs
|
||||
kubeconfig := outputs["aks_kube_config"].Value.(string)
|
||||
aksHost := outputs["aks_host"].Value.(string)
|
||||
aksCert := outputs["aks_client_certificate"].Value.(string)
|
||||
aksKey := outputs["aks_client_key"].Value.(string)
|
||||
aksCa := outputs["aks_cluster_ca_certificate"].Value.(string)
|
||||
azdoPat := outputs["shared_pat"].Value.(string)
|
||||
idRsa := outputs["shared_id_rsa"].Value.(string)
|
||||
idRsaPub := outputs["shared_id_rsa_pub"].Value.(string)
|
||||
fleetInfraRepository := outputs["fleet_infra_repository"].Value.(map[string]interface{})
|
||||
applicationRepository := outputs["application_repository"].Value.(map[string]interface{})
|
||||
fluxAzureSp := outputs["flux_azure_sp"].Value.(map[string]interface{})
|
||||
sharedSopsId := outputs["sops_id"].Value.(string)
|
||||
acr := outputs["acr"].Value.(map[string]interface{})
|
||||
eventHubSas := outputs["event_hub_sas"].Value.(string)
|
||||
|
||||
log.Println("Creating Kubernetes client")
|
||||
kubeconfigPath, kubeClient, err := getKubernetesCredentials(kubeconfig, aksHost, aksCert, aksKey, aksCa)
|
||||
if err != nil {
|
||||
log.Fatalf("error create Kubernetes client: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(filepath.Dir(kubeconfigPath))
|
||||
|
||||
cfg = config{
|
||||
kubeconfigPath: kubeconfigPath,
|
||||
kubeClient: kubeClient,
|
||||
azdoPat: azdoPat,
|
||||
idRsa: idRsa,
|
||||
idRsaPub: idRsaPub,
|
||||
knownHosts: "ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H",
|
||||
fleetInfraRepository: repoConfig{
|
||||
http: fleetInfraRepository["http"].(string),
|
||||
ssh: fleetInfraRepository["ssh"].(string),
|
||||
},
|
||||
applicationRepository: repoConfig{
|
||||
http: applicationRepository["http"].(string),
|
||||
ssh: applicationRepository["ssh"].(string),
|
||||
},
|
||||
fluxAzureSp: spConfig{
|
||||
tenantId: fluxAzureSp["tenant_id"].(string),
|
||||
clientId: fluxAzureSp["client_id"].(string),
|
||||
clientSecret: fluxAzureSp["client_secret"].(string),
|
||||
},
|
||||
sopsId: sharedSopsId,
|
||||
acr: acrConfig{
|
||||
url: acr["url"].(string),
|
||||
username: acr["username"].(string),
|
||||
password: acr["password"].(string),
|
||||
},
|
||||
eventHubSas: eventHubSas,
|
||||
}
|
||||
|
||||
err = installFlux(ctx, kubeClient, kubeconfigPath, cfg.fleetInfraRepository.http, azdoPat, cfg.fluxAzureSp)
|
||||
if err != nil {
|
||||
log.Fatalf("error installing Flux: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Running Azure e2e tests")
|
||||
exitVal := m.Run()
|
||||
|
||||
log.Println("Tearing down Azure test infrastructure")
|
||||
err = tf.Destroy(ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("error running Show: %v", err)
|
||||
}
|
||||
|
||||
os.Exit(exitVal)
|
||||
}
|
||||
|
||||
func TestFluxInstallation(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, "flux-system", "flux-system")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 60*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestAzureDevOpsCloning(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
branchName := "feature/branch"
|
||||
tagName := "v1"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
refType string
|
||||
cloneType string
|
||||
}{
|
||||
{
|
||||
name: "https-feature-branch",
|
||||
refType: "branch",
|
||||
cloneType: "http",
|
||||
},
|
||||
{
|
||||
name: "https-v1",
|
||||
refType: "tag",
|
||||
cloneType: "http",
|
||||
},
|
||||
{
|
||||
name: "ssh-feature-branch",
|
||||
refType: "branch",
|
||||
cloneType: "ssh",
|
||||
},
|
||||
{
|
||||
name: "ssh-v1",
|
||||
refType: "tag",
|
||||
cloneType: "ssh",
|
||||
},
|
||||
}
|
||||
|
||||
t.Log("Creating application sources")
|
||||
repo, repoDir, err := getRepository(cfg.applicationRepository.http, branchName, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
for _, tt := range tests {
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, tt.name)
|
||||
err = runCommand(ctx, repoDir, fmt.Sprintf("mkdir -p ./cloning-test/%s", tt.name))
|
||||
require.NoError(t, err)
|
||||
err = runCommand(ctx, repoDir, fmt.Sprintf("echo '%s' > ./cloning-test/%s/configmap.yaml", manifest, tt.name))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
err = commitAndPushAll(repo, branchName, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
err = createTagAndPush(repo, branchName, tagName, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log("Verifying application-gitops namespaces")
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ref := &sourcev1.GitRepositoryRef{
|
||||
Branch: branchName,
|
||||
}
|
||||
if tt.refType == "tag" {
|
||||
ref = &sourcev1.GitRepositoryRef{
|
||||
Tag: tagName,
|
||||
}
|
||||
}
|
||||
url := cfg.applicationRepository.http
|
||||
secretData := map[string]string{
|
||||
"username": "git",
|
||||
"password": cfg.azdoPat,
|
||||
}
|
||||
if tt.cloneType == "ssh" {
|
||||
url = cfg.applicationRepository.ssh
|
||||
secretData = map[string]string{
|
||||
"identity": cfg.idRsa,
|
||||
"identity.pub": cfg.idRsaPub,
|
||||
"known_hosts": cfg.knownHosts,
|
||||
}
|
||||
}
|
||||
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: tt.name,
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &namespace, func() error {
|
||||
return nil
|
||||
})
|
||||
gitSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "git-credentials",
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, gitSecret, func() error {
|
||||
gitSecret.StringData = secretData
|
||||
return nil
|
||||
})
|
||||
source := &sourcev1.GitRepository{ObjectMeta: metav1.ObjectMeta{Name: tt.name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, source, func() error {
|
||||
source.Spec = sourcev1.GitRepositorySpec{
|
||||
GitImplementation: sourcev1.LibGit2Implementation,
|
||||
Reference: ref,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: gitSecret.Name,
|
||||
},
|
||||
URL: url,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: tt.name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec = kustomizev1.KustomizationSpec{
|
||||
Path: fmt.Sprintf("./cloning-test/%s", tt.name),
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: tt.name,
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
Interval: metav1.Duration{Duration: 1 * time.Minute},
|
||||
Prune: true,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for configmap to be deployed
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, namespace.Name, tt.name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
nn := types.NamespacedName{Name: "foobar", Namespace: namespace.Name}
|
||||
cm := &corev1.ConfigMap{}
|
||||
err = cfg.kubeClient.Get(ctx, nn, cm)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 120*time.Second, 5*time.Second)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageRepositoryACR(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "image-repository-acr"
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
oldVersion := "1.0.0"
|
||||
newVersion := "1.0.1"
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: %s
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: %s/container/podinfo:%s # {"$imagepolicy": "%s:podinfo"}
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/readyz
|
||||
initialDelaySeconds: 5
|
||||
timeoutSeconds: 5`, name, cfg.acr.url, oldVersion, name)
|
||||
|
||||
repo, repoDir, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
err = addFile(repoDir, "podinfo.yaml", manifest)
|
||||
require.NoError(t, err)
|
||||
err = commitAndPushAll(repo, name, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
acrSecret := corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "acr-docker", Namespace: name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &acrSecret, func() error {
|
||||
acrSecret.Type = corev1.SecretTypeDockerConfigJson
|
||||
acrSecret.StringData = map[string]string{
|
||||
".dockerconfigjson": fmt.Sprintf(`
|
||||
{
|
||||
"auths": {
|
||||
"%s": {
|
||||
"auth": "%s"
|
||||
}
|
||||
}
|
||||
}
|
||||
`, cfg.acr.url, b64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", cfg.acr.username, cfg.acr.password)))),
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
imageRepository := reflectorv1beta1.ImageRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &imageRepository, func() error {
|
||||
imageRepository.Spec = reflectorv1beta1.ImageRepositorySpec{
|
||||
Image: fmt.Sprintf("%s/container/podinfo", cfg.acr.url),
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: acrSecret.Name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
imagePolicy := reflectorv1beta1.ImagePolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &imagePolicy, func() error {
|
||||
imagePolicy.Spec = reflectorv1beta1.ImagePolicySpec{
|
||||
ImageRepositoryRef: meta.NamespacedObjectReference{
|
||||
Name: imageRepository.Name,
|
||||
},
|
||||
Policy: reflectorv1beta1.ImagePolicyChoice{
|
||||
SemVer: &reflectorv1beta1.SemVerPolicy{
|
||||
Range: "1.0.x",
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
imageAutomation := automationv1beta1.ImageUpdateAutomation{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &imageAutomation, func() error {
|
||||
imageAutomation.Spec = automationv1beta1.ImageUpdateAutomationSpec{
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
SourceRef: automationv1beta1.SourceReference{
|
||||
Kind: "GitRepository",
|
||||
Name: name,
|
||||
},
|
||||
GitSpec: &automationv1beta1.GitSpec{
|
||||
Checkout: &automationv1beta1.GitCheckoutSpec{
|
||||
Reference: sourcev1.GitRepositoryRef{
|
||||
Branch: name,
|
||||
},
|
||||
},
|
||||
Commit: automationv1beta1.CommitSpec{
|
||||
Author: automationv1beta1.CommitUser{
|
||||
Email: "imageautomation@example.com",
|
||||
Name: "imageautomation",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for image repository to be ready
|
||||
require.Eventually(t, func() bool {
|
||||
_, repoDir, err := getRepository(repoUrl, name, false, cfg.azdoPat)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
b, err := os.ReadFile(filepath.Join(repoDir, "podinfo.yaml"))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if bytes.Contains(b, []byte(newVersion)) == false {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 120*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestKeyVaultSops(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "key-vault-sops"
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
secretYaml := `apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: "test"
|
||||
namespace: "key-vault-sops"
|
||||
stringData:
|
||||
foo: "bar"`
|
||||
|
||||
repo, tmpDir, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
err = runCommand(ctx, tmpDir, "mkdir -p ./key-vault-sops")
|
||||
require.NoError(t, err)
|
||||
err = runCommand(ctx, tmpDir, fmt.Sprintf("echo \"%s\" > ./key-vault-sops/secret.enc.yaml", secretYaml))
|
||||
require.NoError(t, err)
|
||||
err = runCommand(ctx, tmpDir, fmt.Sprintf("sops --encrypt --encrypted-regex '^(data|stringData)$' --azure-kv %s --in-place ./key-vault-sops/secret.enc.yaml", cfg.sopsId))
|
||||
require.NoError(t, err)
|
||||
err = commitAndPushAll(repo, name, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
source := &sourcev1.GitRepository{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, source, func() error {
|
||||
source.Spec = sourcev1.GitRepositorySpec{
|
||||
GitImplementation: sourcev1.LibGit2Implementation,
|
||||
Reference: &sourcev1.GitRepositoryRef{
|
||||
Branch: name,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: "https-credentials",
|
||||
},
|
||||
URL: repoUrl,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec = kustomizev1.KustomizationSpec{
|
||||
Path: "./key-vault-sops",
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: source.Name,
|
||||
Namespace: source.Namespace,
|
||||
},
|
||||
Interval: metav1.Duration{Duration: 1 * time.Minute},
|
||||
Prune: true,
|
||||
Decryption: &kustomizev1.Decryption{
|
||||
Provider: "sops",
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
nn := types.NamespacedName{Name: "test", Namespace: name}
|
||||
secret := &corev1.Secret{}
|
||||
err = cfg.kubeClient.Get(ctx, nn, secret)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 120*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestAzureDevOpsCommitStatus(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "commit-status"
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, name)
|
||||
|
||||
repo, repoDir, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
err = addFile(repoDir, "configmap.yaml", manifest)
|
||||
require.NoError(t, err)
|
||||
err = commitAndPushAll(repo, name, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec.HealthChecks = []meta.NamespacedObjectKindReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Name: "foobar",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, name, name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
secret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "azuredevops-token",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &secret, func() error {
|
||||
secret.StringData = map[string]string{
|
||||
"token": cfg.azdoPat,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
provider := notiv1beta1.Provider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "azuredevops",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &provider, func() error {
|
||||
provider.Spec = notiv1beta1.ProviderSpec{
|
||||
Type: "azuredevops",
|
||||
Address: repoUrl,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: "azuredevops-token",
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
alert := notiv1beta1.Alert{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "azuredevops",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &alert, func() error {
|
||||
alert.Spec = notiv1beta1.AlertSpec{
|
||||
ProviderRef: meta.LocalObjectReference{
|
||||
Name: provider.Name,
|
||||
},
|
||||
EventSources: []notiv1beta1.CrossNamespaceObjectReference{
|
||||
{
|
||||
Kind: "Kustomization",
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
u, err := giturls.Parse(repoUrl)
|
||||
require.NoError(t, err)
|
||||
id := strings.TrimLeft(u.Path, "/")
|
||||
id = strings.TrimSuffix(id, ".git")
|
||||
comp := strings.Split(id, "/")
|
||||
orgUrl := fmt.Sprintf("%s://%s/%v", u.Scheme, u.Host, comp[0])
|
||||
project := comp[1]
|
||||
repoId := comp[3]
|
||||
branch, err := repo.LookupBranch(name, git2go.BranchLocal)
|
||||
require.NoError(t, err)
|
||||
commit, err := repo.LookupCommit(branch.Target())
|
||||
rev := commit.Id().String()
|
||||
connection := azuredevops.NewPatConnection(orgUrl, cfg.azdoPat)
|
||||
client, err := git.NewClient(ctx, connection)
|
||||
require.NoError(t, err)
|
||||
getArgs := git.GetStatusesArgs{
|
||||
Project: &project,
|
||||
RepositoryId: &repoId,
|
||||
CommitId: &rev,
|
||||
}
|
||||
require.Eventually(t, func() bool {
|
||||
statuses, err := client.GetStatuses(ctx, getArgs)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if len(*statuses) != 1 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 500*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestEventHubNotification(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "event-hub"
|
||||
|
||||
// Start listening to eventhub with latest offset
|
||||
hub, err := eventhub.NewHubFromConnectionString(cfg.eventHubSas)
|
||||
require.NoError(t, err)
|
||||
c := make(chan string, 10)
|
||||
handler := func(ctx context.Context, event *eventhub.Event) error {
|
||||
c <- string(event.Data)
|
||||
return nil
|
||||
}
|
||||
runtimeInfo, err := hub.GetRuntimeInformation(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(runtimeInfo.PartitionIDs))
|
||||
listenerHandler, err := hub.Receive(ctx, runtimeInfo.PartitionIDs[0], handler, eventhub.ReceiveWithLatestOffset())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Setup Flux resources
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, name)
|
||||
|
||||
repo, repoDir, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
err = addFile(repoDir, "configmap.yaml", manifest)
|
||||
require.NoError(t, err)
|
||||
err = commitAndPushAll(repo, name, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
secret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &secret, func() error {
|
||||
secret.StringData = map[string]string{
|
||||
"address": cfg.eventHubSas,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
provider := notiv1beta1.Provider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &provider, func() error {
|
||||
provider.Spec = notiv1beta1.ProviderSpec{
|
||||
Type: "azureeventhub",
|
||||
Address: repoUrl,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
alert := notiv1beta1.Alert{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &alert, func() error {
|
||||
alert.Spec = notiv1beta1.AlertSpec{
|
||||
ProviderRef: meta.LocalObjectReference{
|
||||
Name: provider.Name,
|
||||
},
|
||||
EventSources: []notiv1beta1.CrossNamespaceObjectReference{
|
||||
{
|
||||
Kind: "Kustomization",
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec.HealthChecks = []meta.NamespacedObjectKindReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Name: "foobar",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, name, name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 60*time.Second, 5*time.Second)
|
||||
|
||||
// Wait to read even from event hub
|
||||
require.Eventually(t, func() bool {
|
||||
select {
|
||||
case eventJson := <-c:
|
||||
event := &events.Event{}
|
||||
err := json.Unmarshal([]byte(eventJson), event)
|
||||
if err != nil {
|
||||
t.Logf("the received event type does not match Flux format, error: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
if event.InvolvedObject.Kind == kustomizev1.KustomizationKind &&
|
||||
strings.Contains(event.Message, "Health check passed") {
|
||||
return true
|
||||
}
|
||||
|
||||
t.Logf("event received from '%s/%s': %s",
|
||||
event.InvolvedObject.Kind, event.InvolvedObject.Name, event.Message)
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}, 60*time.Second, 1*time.Second)
|
||||
err = listenerHandler.Close(ctx)
|
||||
require.NoError(t, err)
|
||||
err = hub.Close(ctx)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TODO: Enable when source-controller supports Helm charts from OCI sources.
|
||||
/*func TestACRHelmRelease(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
|
||||
// Create namespace for test
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "acr-helm-release",
|
||||
},
|
||||
}
|
||||
err := kubeClient.Create(ctx, &namespace)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
kubeClient.Delete(ctx, &namespace)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
// Copy ACR credentials to new namespace
|
||||
acrNn := types.NamespacedName{
|
||||
Name: "acr-helm",
|
||||
Namespace: "flux-system",
|
||||
}
|
||||
acrSecret := corev1.Secret{}
|
||||
err = kubeClient.Get(ctx, acrNn, &acrSecret)
|
||||
require.NoError(t, err)
|
||||
acrSecret.ObjectMeta = metav1.ObjectMeta{
|
||||
Name: acrSecret.Name,
|
||||
Namespace: namespace.Name,
|
||||
}
|
||||
err = kubeClient.Create(ctx, &acrSecret)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create HelmRepository and wait for it to sync
|
||||
helmRepository := sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "acr",
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
URL: "https://acrappsoarfish.azurecr.io/helm/podinfo",
|
||||
Interval: metav1.Duration{
|
||||
Duration: 5 * time.Minute,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: acrSecret.Name,
|
||||
},
|
||||
PassCredentials: true,
|
||||
},
|
||||
}
|
||||
err = kubeClient.Create(ctx, &helmRepository)
|
||||
require.NoError(t, err)
|
||||
}*/
|
||||
24
tests/azure/go.mod
Normal file
24
tests/azure/go.mod
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
module github.com/fluxcd/flux2/tests/azure
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-event-hubs-go/v3 v3.3.13
|
||||
github.com/fluxcd/helm-controller/api v0.12.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.15.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.12.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.15.2
|
||||
github.com/fluxcd/notification-controller/api v0.17.0
|
||||
github.com/fluxcd/pkg/apis/meta v0.10.1
|
||||
github.com/fluxcd/pkg/runtime v0.12.1
|
||||
github.com/fluxcd/source-controller/api v0.16.0
|
||||
github.com/hashicorp/terraform-exec v0.14.0
|
||||
github.com/libgit2/git2go/v31 v31.6.1
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/whilp/git-urls v1.0.0
|
||||
k8s.io/api v0.22.2
|
||||
k8s.io/apimachinery v0.22.2
|
||||
k8s.io/client-go v0.22.2
|
||||
sigs.k8s.io/controller-runtime v0.10.1
|
||||
)
|
||||
1095
tests/azure/go.sum
Normal file
1095
tests/azure/go.sum
Normal file
File diff suppressed because it is too large
Load diff
19
tests/azure/terraform.go
Normal file
19
tests/azure/terraform.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type whichTerraform struct{}
|
||||
|
||||
func (w *whichTerraform) ExecPath(ctx context.Context) (string, error) {
|
||||
cmd := exec.CommandContext(ctx, "which", "terraform")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
path := strings.TrimSuffix(string(output), "\n")
|
||||
return path, nil
|
||||
}
|
||||
78
tests/azure/terraform/aks/.terraform.lock.hcl
Normal file
78
tests/azure/terraform/aks/.terraform.lock.hcl
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azuread" {
|
||||
version = "1.6.0"
|
||||
constraints = "1.6.0"
|
||||
hashes = [
|
||||
"h1:BlO53mX+Y2W//YqlCKvoxzofegFQk636XlKtmZYH0PY=",
|
||||
"zh:0db70045a464d325fdb3d71809f0467844c3e2fcf1349e568bc51ad5035c99d9",
|
||||
"zh:3629f1d7b4eba48d744b24c7cf7fe878d5ef5910a36b525507bd3d588010ccec",
|
||||
"zh:5a73a45b6d1ff353810cc9b00d7c90a2fb328ba0a9ef3d24392b1500fb98741a",
|
||||
"zh:7a6a9c390cf1bf752321abb8d0643c9f623e8c2ad871dfb378d64c9d90fada2d",
|
||||
"zh:7d6de55d326b046dabc16bd7b655f008ff780c36ffc884b139a7c7da37b446d5",
|
||||
"zh:8d725c618396ccae290e411296c892e08e776c3e9e5a82b0ef1f633a917146ec",
|
||||
"zh:a206d1d8042bf66ca12b97334bbd6fcdf12fd6131f8cb4547c82b9fa7a701612",
|
||||
"zh:b03ab4ff07dcb5ed8be8b0619c6ec9fb0da0c83594ccb0a1bff72f346083b530",
|
||||
"zh:b6131f9d438b340a4016c770b569139ec7ac2532358a8ab783234e8c93d141d5",
|
||||
"zh:ce9372d38e9e62accfd54f4669753000d3dcbae4b45686d74630eb63eb879f37",
|
||||
"zh:df9a607c333d464d8bdeb248b1ff41e493c1d0661453a1e1ce396b89952a74ee",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azurerm" {
|
||||
version = "2.76.0"
|
||||
constraints = "2.76.0"
|
||||
hashes = [
|
||||
"h1:kF+u0s0DPnE5gMKhzQACWRUIdwZG1Ax4atXt9hk1J8M=",
|
||||
"zh:137eb7c07d3d3c9fe123e74381c108c4442efba9fc051faa2ca603503ff2840f",
|
||||
"zh:142a354dffd59a1d6b7f1614ab66a468ace3636d95933589a8d704ee8dbc4ea6",
|
||||
"zh:4c343b4da8b86e4213c1b11f73337cec73a55b1fa95a0e0e0c79f34597d37cc3",
|
||||
"zh:75d3109d48726fdbaad840d2fa294ec3362b32a3628c261af00f5c5608427521",
|
||||
"zh:7b1e78c144c6ad2beebc798abb9e76c725bf34ced41df36dc0120a0f2426e801",
|
||||
"zh:981235b01c3d4acf94c78cdd96624fd01d0a3622bc06b5c62aef3e788f1481c3",
|
||||
"zh:bad819efae7293ce371409e1ed34197c3e879f61d3e44893af0ce68e6aaffde7",
|
||||
"zh:c8008967722929deccfec9695754ae55028ce12311c321ae7a7c753dde162a44",
|
||||
"zh:d38513d1138864269b2ff333b08a64a7949630d489f18e660630bbaff3b7ebb8",
|
||||
"zh:e1f64d2d91b5f5cba6a9c5d35278a4918d332d7385a87f8e3466aaadb782a90f",
|
||||
"zh:e93a377a1e823df69718686703b07f1712046eeb742006022e982f2e8a594161",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.1.0"
|
||||
hashes = [
|
||||
"h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=",
|
||||
"zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc",
|
||||
"zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626",
|
||||
"zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff",
|
||||
"zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2",
|
||||
"zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992",
|
||||
"zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427",
|
||||
"zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc",
|
||||
"zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f",
|
||||
"zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b",
|
||||
"zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7",
|
||||
"zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/microsoft/azuredevops" {
|
||||
version = "0.1.7"
|
||||
constraints = "0.1.7"
|
||||
hashes = [
|
||||
"h1:AWNWqJ3XhlKp3xdJF+3WKdK1zVoCFYInQvi06exsBzg=",
|
||||
"zh:0c024992f2282ef73d4829e487ec8482dd98e9272b903f2e5979f5f62567ee4e",
|
||||
"zh:47fef8f57dfdca6aebe5a907b4866880007512019d9bec29805fc83501412309",
|
||||
"zh:692736c501c6b987a4a74c69fb7702a54969180706d1f67eff13e6ed2a0f9fec",
|
||||
"zh:6c3c4339206f5dcbc9d10fb2fe343652e7e14255223dcece5bf79ef9030858ef",
|
||||
"zh:77dfc63377b8d8fe24cbbe479ead18bfd1c7ded067fd694b6532434d6305ad31",
|
||||
"zh:93dba26dbade208a1cba43333f104a64252ca2404636ab033702da29648bfaaa",
|
||||
"zh:952d28b3e6c137de9b8700d2b748e5a4a2aa53ed07005f0f7abdd66b84cc63fe",
|
||||
"zh:a7b8238b8b2f04ad2d720a207377bfc2066d54b1d9d7285f2535afc43ff80fdb",
|
||||
"zh:bb23d8fc3cdd3c01d7620dadb2ba7b724706f2112d7738e135d1be1455682f5e",
|
||||
"zh:cb4da640beb5fc59296479c201a03351789496c04aaa57ae1530a7aac9095b92",
|
||||
"zh:ede6fb7ab598081fdddac56d470bae14448271dfd43a645bc02d136643391ebe",
|
||||
"zh:fd8291e6dc9118323a744660326a0f11de2a475c4a358e50f480feed1f3bb080",
|
||||
]
|
||||
}
|
||||
37
tests/azure/terraform/aks/aks.tf
Normal file
37
tests/azure/terraform/aks/aks.tf
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
resource "azurerm_kubernetes_cluster" "this" {
|
||||
name = "aks-${local.name_suffix}"
|
||||
location = azurerm_resource_group.this.location
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
|
||||
dns_prefix = "aks${local.name_suffix}"
|
||||
|
||||
default_node_pool {
|
||||
name = "default"
|
||||
node_count = 2
|
||||
vm_size = "Standard_B2s"
|
||||
os_disk_size_gb = 30
|
||||
}
|
||||
|
||||
identity {
|
||||
type = "SystemAssigned"
|
||||
}
|
||||
|
||||
role_based_access_control {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
network_profile {
|
||||
network_plugin = "kubenet"
|
||||
network_policy = "calico"
|
||||
}
|
||||
|
||||
tags = {
|
||||
environment = "e2e"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "aks_acr_pull" {
|
||||
scope = data.azurerm_container_registry.shared.id
|
||||
role_definition_name = "AcrPull"
|
||||
principal_id = azurerm_kubernetes_cluster.this.kubelet_identity[0].object_id
|
||||
}
|
||||
21
tests/azure/terraform/aks/azuredevops.tf
Normal file
21
tests/azure/terraform/aks/azuredevops.tf
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
data "azuredevops_project" "e2e" {
|
||||
name = "e2e"
|
||||
}
|
||||
|
||||
resource "azuredevops_git_repository" "fleet_infra" {
|
||||
project_id = data.azuredevops_project.e2e.id
|
||||
name = "fleet-infra-${local.name_suffix}"
|
||||
default_branch = "refs/heads/main"
|
||||
initialization {
|
||||
init_type = "Clean"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuredevops_git_repository" "application" {
|
||||
project_id = data.azuredevops_project.e2e.id
|
||||
name = "application-${local.name_suffix}"
|
||||
default_branch = "refs/heads/main"
|
||||
initialization {
|
||||
init_type = "Clean"
|
||||
}
|
||||
}
|
||||
26
tests/azure/terraform/aks/event-hub.tf
Normal file
26
tests/azure/terraform/aks/event-hub.tf
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
resource "azurerm_eventhub_namespace" "this" {
|
||||
name = "ehns-${local.name_suffix}"
|
||||
location = azurerm_resource_group.this.location
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
sku = "Standard"
|
||||
capacity = 1
|
||||
}
|
||||
|
||||
|
||||
resource "azurerm_eventhub" "this" {
|
||||
name = "eh-${local.name_suffix}"
|
||||
namespace_name = azurerm_eventhub_namespace.this.name
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
partition_count = 1
|
||||
message_retention = 1
|
||||
}
|
||||
|
||||
resource "azurerm_eventhub_authorization_rule" "this" {
|
||||
name = "flux"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
namespace_name = azurerm_eventhub_namespace.this.name
|
||||
eventhub_name = azurerm_eventhub.this.name
|
||||
listen = true
|
||||
send = true
|
||||
manage = false
|
||||
}
|
||||
37
tests/azure/terraform/aks/keyvault.tf
Normal file
37
tests/azure/terraform/aks/keyvault.tf
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
resource "azurerm_key_vault" "this" {
|
||||
name = "kv-${random_pet.suffix.id}"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
location = azurerm_resource_group.this.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "sops_write" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = data.azurerm_client_config.current.object_id
|
||||
|
||||
key_permissions = [
|
||||
"Encrypt",
|
||||
"Decrypt",
|
||||
"Create",
|
||||
"Delete",
|
||||
"Purge",
|
||||
"Get",
|
||||
"List",
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_key" "sops" {
|
||||
depends_on = [azurerm_key_vault_access_policy.sops_write]
|
||||
|
||||
name = "sops"
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
key_type = "RSA"
|
||||
key_size = 2048
|
||||
|
||||
key_opts = [
|
||||
"decrypt",
|
||||
"encrypt",
|
||||
]
|
||||
}
|
||||
52
tests/azure/terraform/aks/main.tf
Normal file
52
tests/azure/terraform/aks/main.tf
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "terraform-state"
|
||||
storage_account_name = "terraformstate0419"
|
||||
container_name = "aks-tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
}
|
||||
|
||||
required_version = "1.0.7"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "2.76.0"
|
||||
}
|
||||
azuread = {
|
||||
source = "hashicorp/azuread"
|
||||
version = "1.6.0"
|
||||
}
|
||||
azuredevops = {
|
||||
source = "microsoft/azuredevops"
|
||||
version = "0.1.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
||||
|
||||
provider "azuredevops" {
|
||||
org_service_url = "https://dev.azure.com/${local.azure_devops_org}"
|
||||
personal_access_token = data.azurerm_key_vault_secret.shared_pat.value
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
resource "random_pet" "suffix" {}
|
||||
|
||||
locals {
|
||||
azure_devops_org = "flux-azure"
|
||||
name_suffix = "e2e-${random_pet.suffix.id}"
|
||||
}
|
||||
|
||||
resource "azurerm_resource_group" "this" {
|
||||
name = "rg-${local.name_suffix}"
|
||||
location = "West Europe"
|
||||
|
||||
tags = {
|
||||
environment = "e2e"
|
||||
}
|
||||
}
|
||||
76
tests/azure/terraform/aks/outputs.tf
Normal file
76
tests/azure/terraform/aks/outputs.tf
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
output "aks_kube_config" {
|
||||
sensitive = true
|
||||
value = azurerm_kubernetes_cluster.this.kube_config_raw
|
||||
}
|
||||
|
||||
output "aks_host" {
|
||||
value = azurerm_kubernetes_cluster.this.kube_config[0].host
|
||||
}
|
||||
|
||||
output "aks_client_certificate" {
|
||||
value = base64decode(azurerm_kubernetes_cluster.this.kube_config[0].client_certificate)
|
||||
}
|
||||
|
||||
output "aks_client_key" {
|
||||
value = base64decode(azurerm_kubernetes_cluster.this.kube_config[0].client_key)
|
||||
}
|
||||
|
||||
output "aks_cluster_ca_certificate" {
|
||||
value = base64decode(azurerm_kubernetes_cluster.this.kube_config[0].cluster_ca_certificate)
|
||||
}
|
||||
|
||||
output "shared_pat" {
|
||||
sensitive = true
|
||||
value = data.azurerm_key_vault_secret.shared_pat.value
|
||||
}
|
||||
|
||||
output "shared_id_rsa" {
|
||||
sensitive = true
|
||||
value = data.azurerm_key_vault_secret.shared_id_rsa.value
|
||||
}
|
||||
|
||||
output "shared_id_rsa_pub" {
|
||||
sensitive = true
|
||||
value = data.azurerm_key_vault_secret.shared_id_rsa_pub.value
|
||||
}
|
||||
|
||||
output "fleet_infra_repository" {
|
||||
value = {
|
||||
http = azuredevops_git_repository.fleet_infra.remote_url
|
||||
ssh = "ssh://git@ssh.dev.azure.com/v3/${local.azure_devops_org}/${azuredevops_git_repository.fleet_infra.project_id}/${azuredevops_git_repository.fleet_infra.name}"
|
||||
}
|
||||
}
|
||||
|
||||
output "application_repository" {
|
||||
value = {
|
||||
http = azuredevops_git_repository.application.remote_url
|
||||
ssh = "ssh://git@ssh.dev.azure.com/v3/${local.azure_devops_org}/${azuredevops_git_repository.application.project_id}/${azuredevops_git_repository.application.name}"
|
||||
}
|
||||
}
|
||||
|
||||
output "flux_azure_sp" {
|
||||
value = {
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
client_id = azuread_service_principal.flux.application_id
|
||||
client_secret = azuread_service_principal_password.flux.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "event_hub_sas" {
|
||||
value = azurerm_eventhub_authorization_rule.this.primary_connection_string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "sops_id" {
|
||||
value = azurerm_key_vault_key.sops.id
|
||||
}
|
||||
|
||||
output "acr" {
|
||||
value = {
|
||||
url = data.azurerm_container_registry.shared.login_server
|
||||
username = azuread_service_principal.flux.application_id
|
||||
password = azuread_service_principal_password.flux.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
52
tests/azure/terraform/aks/service-principal.tf
Normal file
52
tests/azure/terraform/aks/service-principal.tf
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
resource "azuread_application" "flux" {
|
||||
display_name = "flux-${local.name_suffix}"
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000003-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "df021288-bdef-4463-88db-98f22de89214"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000002-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "1cda74f2-2616-4834-b122-5cb1b07f8a59"
|
||||
type = "Role"
|
||||
}
|
||||
resource_access {
|
||||
id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuread_service_principal" "flux" {
|
||||
application_id = azuread_application.flux.application_id
|
||||
}
|
||||
|
||||
resource "azuread_service_principal_password" "flux" {
|
||||
service_principal_id = azuread_service_principal.flux.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "acr" {
|
||||
scope = data.azurerm_container_registry.shared.id
|
||||
role_definition_name = "AcrPull"
|
||||
principal_id = azuread_service_principal.flux.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "sops_decrypt" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = azuread_service_principal.flux.object_id
|
||||
|
||||
key_permissions = [
|
||||
"Encrypt",
|
||||
"Decrypt",
|
||||
"Get",
|
||||
"List",
|
||||
]
|
||||
}
|
||||
32
tests/azure/terraform/aks/shared.tf
Normal file
32
tests/azure/terraform/aks/shared.tf
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
locals {
|
||||
shared_suffix = "oarfish"
|
||||
}
|
||||
|
||||
data "azurerm_resource_group" "shared" {
|
||||
name = "e2e-shared"
|
||||
}
|
||||
|
||||
data "azurerm_container_registry" "shared" {
|
||||
name = "acrapps${local.shared_suffix}"
|
||||
resource_group_name = data.azurerm_resource_group.shared.name
|
||||
}
|
||||
|
||||
data "azurerm_key_vault" "shared" {
|
||||
resource_group_name = data.azurerm_resource_group.shared.name
|
||||
name = "kv-credentials-${local.shared_suffix}"
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "shared_pat" {
|
||||
key_vault_id = data.azurerm_key_vault.shared.id
|
||||
name = "pat"
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "shared_id_rsa" {
|
||||
key_vault_id = data.azurerm_key_vault.shared.id
|
||||
name = "id-rsa"
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "shared_id_rsa_pub" {
|
||||
key_vault_id = data.azurerm_key_vault.shared.id
|
||||
name = "id-rsa-pub"
|
||||
}
|
||||
58
tests/azure/terraform/shared/.terraform.lock.hcl
Normal file
58
tests/azure/terraform/shared/.terraform.lock.hcl
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azuread" {
|
||||
version = "1.6.0"
|
||||
constraints = "1.6.0"
|
||||
hashes = [
|
||||
"h1:BlO53mX+Y2W//YqlCKvoxzofegFQk636XlKtmZYH0PY=",
|
||||
"zh:0db70045a464d325fdb3d71809f0467844c3e2fcf1349e568bc51ad5035c99d9",
|
||||
"zh:3629f1d7b4eba48d744b24c7cf7fe878d5ef5910a36b525507bd3d588010ccec",
|
||||
"zh:5a73a45b6d1ff353810cc9b00d7c90a2fb328ba0a9ef3d24392b1500fb98741a",
|
||||
"zh:7a6a9c390cf1bf752321abb8d0643c9f623e8c2ad871dfb378d64c9d90fada2d",
|
||||
"zh:7d6de55d326b046dabc16bd7b655f008ff780c36ffc884b139a7c7da37b446d5",
|
||||
"zh:8d725c618396ccae290e411296c892e08e776c3e9e5a82b0ef1f633a917146ec",
|
||||
"zh:a206d1d8042bf66ca12b97334bbd6fcdf12fd6131f8cb4547c82b9fa7a701612",
|
||||
"zh:b03ab4ff07dcb5ed8be8b0619c6ec9fb0da0c83594ccb0a1bff72f346083b530",
|
||||
"zh:b6131f9d438b340a4016c770b569139ec7ac2532358a8ab783234e8c93d141d5",
|
||||
"zh:ce9372d38e9e62accfd54f4669753000d3dcbae4b45686d74630eb63eb879f37",
|
||||
"zh:df9a607c333d464d8bdeb248b1ff41e493c1d0661453a1e1ce396b89952a74ee",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azurerm" {
|
||||
version = "2.76.0"
|
||||
constraints = "2.76.0"
|
||||
hashes = [
|
||||
"h1:kF+u0s0DPnE5gMKhzQACWRUIdwZG1Ax4atXt9hk1J8M=",
|
||||
"zh:137eb7c07d3d3c9fe123e74381c108c4442efba9fc051faa2ca603503ff2840f",
|
||||
"zh:142a354dffd59a1d6b7f1614ab66a468ace3636d95933589a8d704ee8dbc4ea6",
|
||||
"zh:4c343b4da8b86e4213c1b11f73337cec73a55b1fa95a0e0e0c79f34597d37cc3",
|
||||
"zh:75d3109d48726fdbaad840d2fa294ec3362b32a3628c261af00f5c5608427521",
|
||||
"zh:7b1e78c144c6ad2beebc798abb9e76c725bf34ced41df36dc0120a0f2426e801",
|
||||
"zh:981235b01c3d4acf94c78cdd96624fd01d0a3622bc06b5c62aef3e788f1481c3",
|
||||
"zh:bad819efae7293ce371409e1ed34197c3e879f61d3e44893af0ce68e6aaffde7",
|
||||
"zh:c8008967722929deccfec9695754ae55028ce12311c321ae7a7c753dde162a44",
|
||||
"zh:d38513d1138864269b2ff333b08a64a7949630d489f18e660630bbaff3b7ebb8",
|
||||
"zh:e1f64d2d91b5f5cba6a9c5d35278a4918d332d7385a87f8e3466aaadb782a90f",
|
||||
"zh:e93a377a1e823df69718686703b07f1712046eeb742006022e982f2e8a594161",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.1.0"
|
||||
hashes = [
|
||||
"h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=",
|
||||
"zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc",
|
||||
"zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626",
|
||||
"zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff",
|
||||
"zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2",
|
||||
"zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992",
|
||||
"zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427",
|
||||
"zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc",
|
||||
"zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f",
|
||||
"zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b",
|
||||
"zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7",
|
||||
"zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a",
|
||||
]
|
||||
}
|
||||
6
tests/azure/terraform/shared/acr.tf
Normal file
6
tests/azure/terraform/shared/acr.tf
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
resource "azurerm_container_registry" "this" {
|
||||
name = "acrapps${random_pet.suffix.id}"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
location = azurerm_resource_group.this.location
|
||||
sku = "standard"
|
||||
}
|
||||
43
tests/azure/terraform/shared/keyvault.tf
Normal file
43
tests/azure/terraform/shared/keyvault.tf
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
resource "azurerm_key_vault" "this" {
|
||||
name = "kv-credentials-${random_pet.suffix.id}"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
location = azurerm_resource_group.this.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "admin" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = data.azurerm_client_config.current.object_id
|
||||
|
||||
key_permissions = [
|
||||
"Backup",
|
||||
"Create",
|
||||
"Decrypt",
|
||||
"Delete",
|
||||
"Encrypt",
|
||||
"Get",
|
||||
"Import",
|
||||
"List",
|
||||
"Purge",
|
||||
"Recover",
|
||||
"Restore",
|
||||
"Sign",
|
||||
"UnwrapKey",
|
||||
"Update",
|
||||
"Verify",
|
||||
"WrapKey",
|
||||
]
|
||||
|
||||
secret_permissions = [
|
||||
"Backup",
|
||||
"Delete",
|
||||
"Get",
|
||||
"List",
|
||||
"Purge",
|
||||
"Recover",
|
||||
"Restore",
|
||||
"Set",
|
||||
]
|
||||
}
|
||||
39
tests/azure/terraform/shared/main.tf
Normal file
39
tests/azure/terraform/shared/main.tf
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "terraform-state"
|
||||
storage_account_name = "terraformstate0419"
|
||||
container_name = "shared-tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
}
|
||||
|
||||
required_version = "1.0.7"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "2.76.0"
|
||||
}
|
||||
azuread = {
|
||||
source = "hashicorp/azuread"
|
||||
version = "1.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
||||
|
||||
resource "random_pet" "suffix" {
|
||||
length = 1
|
||||
separator = ""
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
data "azurerm_subscription" "current" {}
|
||||
|
||||
resource "azurerm_resource_group" "this" {
|
||||
name = "e2e-shared"
|
||||
location = "West Europe"
|
||||
}
|
||||
18
tests/azure/terraform/shared/outputs.tf
Normal file
18
tests/azure/terraform/shared/outputs.tf
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
output "azure_devops_sp" {
|
||||
value = {
|
||||
client_id = azuread_service_principal.azure_devops.application_id
|
||||
client_secret = azuread_application_password.azure_devops.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "github_sp" {
|
||||
value = {
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
subscription_id = data.azurerm_client_config.current.subscription_id
|
||||
client_id = azuread_service_principal.github.application_id
|
||||
client_secret = azuread_application_password.github.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
105
tests/azure/terraform/shared/service-principal.tf
Normal file
105
tests/azure/terraform/shared/service-principal.tf
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# Service Principal used by Azure DevOps to push OCI and Helm Charts
|
||||
resource "azuread_application" "azure_devops" {
|
||||
display_name = "azure-devops-${random_pet.suffix.id}"
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000003-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "df021288-bdef-4463-88db-98f22de89214"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000002-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "1cda74f2-2616-4834-b122-5cb1b07f8a59"
|
||||
type = "Role"
|
||||
}
|
||||
resource_access {
|
||||
id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuread_application_password" "azure_devops" {
|
||||
display_name = "password"
|
||||
application_object_id = azuread_application.azure_devops.object_id
|
||||
}
|
||||
|
||||
resource "azuread_service_principal" "azure_devops" {
|
||||
application_id = azuread_application.azure_devops.application_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "azure_devops_acr" {
|
||||
scope = azurerm_container_registry.this.id
|
||||
role_definition_name = "Contributor"
|
||||
principal_id = azuread_service_principal.azure_devops.object_id
|
||||
}
|
||||
|
||||
# Service Principal that is used to run the tests in GitHub Actions
|
||||
resource "azuread_application" "github" {
|
||||
display_name = "github-${random_pet.suffix.id}"
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000003-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "df021288-bdef-4463-88db-98f22de89214"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000002-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "1cda74f2-2616-4834-b122-5cb1b07f8a59"
|
||||
type = "Role"
|
||||
}
|
||||
resource_access {
|
||||
id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuread_application_password" "github" {
|
||||
display_name = "password"
|
||||
application_object_id = azuread_application.github.object_id
|
||||
}
|
||||
|
||||
resource "azuread_service_principal" "github" {
|
||||
application_id = azuread_application.github.application_id
|
||||
}
|
||||
|
||||
data "azurerm_storage_account" "terraform_state" {
|
||||
resource_group_name = "terraform-state"
|
||||
name = "terraformstate0419"
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "github_resource_group" {
|
||||
scope = data.azurerm_subscription.current.id
|
||||
role_definition_name = "Contributor"
|
||||
principal_id = azuread_service_principal.github.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "github_acr" {
|
||||
scope = azurerm_container_registry.this.id
|
||||
role_definition_name = "Owner"
|
||||
principal_id = azuread_service_principal.github.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "github_keyvault_secret_read" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = azuread_service_principal.github.object_id
|
||||
|
||||
secret_permissions = [
|
||||
"Get",
|
||||
"List",
|
||||
]
|
||||
}
|
||||
0
tests/azure/terraform/shared/variables.tf
Normal file
0
tests/azure/terraform/shared/variables.tf
Normal file
461
tests/azure/util_test.go
Normal file
461
tests/azure/util_test.go
Normal file
|
|
@ -0,0 +1,461 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
git2go "github.com/libgit2/git2go/v31"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
helmv2beta1 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
automationv1beta1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
reflectorv1beta1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
notiv1beta1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||
)
|
||||
|
||||
const defaultBranch = "main"
|
||||
|
||||
// getKubernetesCredentials returns a path to a kubeconfig file and a kube client instance.
|
||||
func getKubernetesCredentials(kubeconfig, aksHost, aksCert, aksKey, aksCa string) (string, client.Client, error) {
|
||||
tmpDir, err := ioutil.TempDir("", "*-azure-e2e")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
kubeconfigPath := fmt.Sprintf("%s/kubeconfig", tmpDir)
|
||||
os.WriteFile(kubeconfigPath, []byte(kubeconfig), 0750)
|
||||
kubeCfg := &rest.Config{
|
||||
Host: aksHost,
|
||||
TLSClientConfig: rest.TLSClientConfig{
|
||||
CertData: []byte(aksCert),
|
||||
KeyData: []byte(aksKey),
|
||||
CAData: []byte(aksCa),
|
||||
},
|
||||
}
|
||||
err = sourcev1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = kustomizev1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = helmv2beta1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = reflectorv1beta1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = automationv1beta1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = notiv1beta1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
kubeClient, err := client.New(kubeCfg, client.Options{Scheme: scheme.Scheme})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
return kubeconfigPath, kubeClient, nil
|
||||
}
|
||||
|
||||
// installFlux adds the core Flux components to the cluster specified in the kubeconfig file.
|
||||
func installFlux(ctx context.Context, kubeClient client.Client, kubeconfigPath, repoUrl, azdoPat string, sp spConfig) error {
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "flux-system",
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &namespace, func() error {
|
||||
return nil
|
||||
})
|
||||
httpsCredentials := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "https-credentials", Namespace: "flux-system"}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, httpsCredentials, func() error {
|
||||
httpsCredentials.StringData = map[string]string{
|
||||
"username": "git",
|
||||
"password": azdoPat,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
azureSp := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "azure-sp", Namespace: "flux-system"}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, azureSp, func() error {
|
||||
azureSp.StringData = map[string]string{
|
||||
"AZURE_TENANT_ID": sp.tenantId,
|
||||
"AZURE_CLIENT_ID": sp.clientId,
|
||||
"AZURE_CLIENT_SECRET": sp.clientSecret,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Install Flux and push files to git repository
|
||||
repo, repoDir, err := getRepository(repoUrl, defaultBranch, true, azdoPat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = runCommand(ctx, repoDir, "mkdir -p ./clusters/e2e/flux-system")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = runCommand(ctx, repoDir, "flux install --components-extra=\"image-reflector-controller,image-automation-controller\" --export > ./clusters/e2e/flux-system/gotk-components.yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = runCommand(ctx, repoDir, fmt.Sprintf("flux create source git flux-system --git-implementation=libgit2 --url=%s --branch=%s --secret-ref=https-credentials --interval=1m --export > ./clusters/e2e/flux-system/gotk-sync.yaml", repoUrl, defaultBranch))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = runCommand(ctx, repoDir, "flux create kustomization flux-system --source=flux-system --path='./clusters/e2e' --prune=true --interval=1m --export >> ./clusters/e2e/flux-system/gotk-sync.yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kustomizeYaml := `
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kustomize-controller
|
||||
namespace: flux-system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: azure-sp
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: source-controller
|
||||
namespace: flux-system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: azure-sp
|
||||
`
|
||||
err = runCommand(ctx, repoDir, fmt.Sprintf("echo \"%s\" > ./clusters/e2e/flux-system/kustomization.yaml", kustomizeYaml))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = commitAndPushAll(repo, defaultBranch, azdoPat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Need to apply CRDs first to make sure that the sync resources will apply properly
|
||||
err = runCommand(ctx, repoDir, fmt.Sprintf("kubectl --kubeconfig=%s apply -f ./clusters/e2e/flux-system/gotk-components.yaml", kubeconfigPath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = runCommand(ctx, repoDir, fmt.Sprintf("kubectl --kubeconfig=%s apply -k ./clusters/e2e/flux-system/", kubeconfigPath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCommand(ctx context.Context, dir, command string) error {
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Minute)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(timeoutCtx, "bash", "-c", command)
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failure to run command %s: %v", string(output), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyGitAndKustomization checks that the gitrespository and kustomization combination are working properly.
|
||||
func verifyGitAndKustomization(ctx context.Context, kubeClient client.Client, namespace, name string) error {
|
||||
nn := types.NamespacedName{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
}
|
||||
source := &sourcev1.GitRepository{}
|
||||
err := kubeClient.Get(ctx, nn, source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apimeta.IsStatusConditionPresentAndEqual(source.Status.Conditions, meta.ReadyCondition, metav1.ConditionTrue) == false {
|
||||
return fmt.Errorf("source condition not ready")
|
||||
}
|
||||
kustomization := &kustomizev1.Kustomization{}
|
||||
err = kubeClient.Get(ctx, nn, kustomization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apimeta.IsStatusConditionPresentAndEqual(kustomization.Status.Conditions, meta.ReadyCondition, metav1.ConditionTrue) == false {
|
||||
return fmt.Errorf("kustomization condition not ready")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupNamespace(ctx context.Context, kubeClient client.Client, repoUrl, password, name string) error {
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, kubeClient, &namespace, func() error {
|
||||
return nil
|
||||
})
|
||||
secret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "https-credentials",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, &secret, func() error {
|
||||
secret.StringData = map[string]string{
|
||||
"username": "git",
|
||||
"password": password,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
source := &sourcev1.GitRepository{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, source, func() error {
|
||||
source.Spec = sourcev1.GitRepositorySpec{
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
GitImplementation: sourcev1.LibGit2Implementation,
|
||||
Reference: &sourcev1.GitRepositoryRef{
|
||||
Branch: name,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: "https-credentials",
|
||||
},
|
||||
URL: repoUrl,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, kustomization, func() error {
|
||||
kustomization.Spec = kustomizev1.KustomizationSpec{
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: source.Name,
|
||||
Namespace: source.Namespace,
|
||||
},
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
Prune: true,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRepository(url, branchName string, overrideBranch bool, password string) (*git2go.Repository, string, error) {
|
||||
checkoutBranch := defaultBranch
|
||||
if overrideBranch == false {
|
||||
checkoutBranch = branchName
|
||||
}
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "*-repository")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
repo, err := git2go.Clone(url, tmpDir, &git2go.CloneOptions{
|
||||
FetchOptions: &git2go.FetchOptions{
|
||||
RemoteCallbacks: git2go.RemoteCallbacks{
|
||||
CredentialsCallback: credentialCallback("git", password),
|
||||
},
|
||||
},
|
||||
CheckoutBranch: checkoutBranch,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
// Nothing to do further if correct branch is checked out
|
||||
if checkoutBranch == branchName {
|
||||
return repo, tmpDir, nil
|
||||
}
|
||||
head, err := repo.Head()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
headCommit, err := repo.LookupCommit(head.Target())
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
_, err = repo.CreateBranch(branchName, headCommit, true)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return repo, tmpDir, nil
|
||||
}
|
||||
|
||||
func addFile(dir, path, content string) error {
|
||||
err := os.WriteFile(filepath.Join(dir, path), []byte(content), 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func commitAndPushAll(repo *git2go.Repository, branchName, password string) error {
|
||||
idx, err := repo.Index()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = idx.AddAll([]string{}, git2go.IndexAddDefault, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
treeId, err := idx.WriteTree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = idx.Write()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tree, err := repo.LookupTree(treeId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
branch, err := repo.LookupBranch(branchName, git2go.BranchLocal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commitTarget, err := repo.LookupCommit(branch.Target())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig := &git2go.Signature{
|
||||
Name: "git",
|
||||
Email: "test@example.com",
|
||||
When: time.Now(),
|
||||
}
|
||||
_, err = repo.CreateCommit(fmt.Sprintf("refs/heads/%s", branchName), sig, sig, "add file", tree, commitTarget)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
origin, err := repo.Remotes.Lookup("origin")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = origin.Push([]string{fmt.Sprintf("+refs/heads/%s", branchName)}, &git2go.PushOptions{
|
||||
RemoteCallbacks: git2go.RemoteCallbacks{
|
||||
CredentialsCallback: credentialCallback("git", password),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createTagAndPush(repo *git2go.Repository, branchName, tag, password string) error {
|
||||
branch, err := repo.LookupBranch(branchName, git2go.BranchAll)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commit, err := repo.LookupCommit(branch.Target())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags, err := repo.Tags.List()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, existingTag := range tags {
|
||||
if existingTag == tag {
|
||||
err = repo.Tags.Remove(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sig := &git2go.Signature{
|
||||
Name: "git",
|
||||
Email: "test@example.com",
|
||||
When: time.Now(),
|
||||
}
|
||||
_, err = repo.Tags.Create(tag, commit, sig, "create tag")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
origin, err := repo.Remotes.Lookup("origin")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = origin.Push([]string{fmt.Sprintf("+refs/tags/%s", tag)}, &git2go.PushOptions{
|
||||
RemoteCallbacks: git2go.RemoteCallbacks{
|
||||
CredentialsCallback: credentialCallback("git", password),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func credentialCallback(username, password string) git2go.CredentialsCallback {
|
||||
return func(url string, usernameFromURL string, allowedTypes git2go.CredType) (*git2go.Cred, error) {
|
||||
cred, err := git2go.NewCredentialUserpassPlaintext(username, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cred, nil
|
||||
}
|
||||
}
|
||||
|
||||
func getTestManifest(namespace string) string {
|
||||
return fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: %s
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, namespace, namespace)
|
||||
}
|
||||
Loading…
Reference in a new issue