Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
978cc0c5b8 | ||
|
|
4e009a7167 | ||
|
|
176444263c | ||
|
|
87232fd4dd | ||
|
|
0361a08aa0 | ||
|
|
be154d079b | ||
|
|
feccc36415 | ||
|
|
06b8ad2402 | ||
|
|
023a709b6a | ||
|
|
6681cd05a9 | ||
|
|
56807fddf6 | ||
|
|
51504406da | ||
|
|
d28cdd9726 | ||
|
|
c1f120facc | ||
|
|
87f792915a | ||
|
|
9fb5fe3af3 | ||
|
|
0648f56049 | ||
|
|
7da8ffd87f | ||
|
|
79f900b82e | ||
|
|
0394c4d5ef | ||
|
|
693f0c1da1 | ||
|
|
65481c223e | ||
|
|
d2222426f5 | ||
|
|
18924d29a7 | ||
|
|
84a3cdde93 | ||
|
|
e5eb4d4a67 | ||
|
|
60c44c16f5 | ||
|
|
f22222f71d | ||
|
|
287ac6b003 | ||
|
|
5b422bef17 | ||
|
|
1dc3ff6c59 | ||
|
|
ed13067ff2 | ||
|
|
a3151aa10c | ||
|
|
536f4c31ce | ||
|
|
3a8765859d | ||
|
|
369ae5aa71 | ||
|
|
ca2b93ba39 | ||
|
|
8ff8295d0c | ||
|
|
0439154564 | ||
|
|
e7e05f870b | ||
|
|
d54f08e7a9 | ||
|
|
ece3a07567 | ||
|
|
9c37506130 | ||
|
|
58b4ed586a | ||
|
|
c479eb80c6 | ||
|
|
da7af5ab5f | ||
|
|
d1b4851fbe | ||
|
|
a9f53b4f1a | ||
|
|
7327b14a62 | ||
|
|
3d5fc3dc18 | ||
|
|
1d80ff2b09 | ||
|
|
28111d27fb | ||
|
|
ddd377b997 | ||
|
|
e01810037b | ||
|
|
f5563de144 | ||
|
|
8ecaa56461 | ||
|
|
9d38ea6ffc | ||
|
|
f58b82fb4e | ||
|
|
be361a44d5 | ||
|
|
12e065cc43 | ||
|
|
f9e69089ea | ||
|
|
2eced064dd | ||
|
|
7be91884b7 | ||
|
|
b2b610b55e | ||
|
|
21a943e6f9 | ||
|
|
cb1b117d17 | ||
|
|
96f177b101 | ||
|
|
7621418b72 | ||
|
|
7a94a3ac71 | ||
|
|
58b799fa83 | ||
|
|
38635e0ec5 | ||
|
|
d79e49f80b | ||
|
|
5e44b7b1b3 | ||
|
|
131c05d9c7 | ||
|
|
3ac8d54a30 | ||
|
|
c605f9a44f | ||
|
|
eefd47d701 | ||
|
|
0014bc4c43 | ||
|
|
ccf358f0ca | ||
|
|
bd284ab28b | ||
|
|
bed46f6b68 | ||
|
|
fdd3fd1d06 | ||
|
|
e81201b8cb | ||
|
|
2c1085d9ce | ||
|
|
49eb1c5444 | ||
|
|
81dc4adc69 | ||
|
|
8e23989418 | ||
|
|
f532bd2d48 | ||
|
|
da9df03675 | ||
|
|
91965ddfc9 | ||
|
|
0bd78ca80c | ||
|
|
96b96ac78e | ||
|
|
a9a63b8423 | ||
|
|
8abb93e831 | ||
|
|
645f9df4f0 | ||
|
|
6924a16ac7 | ||
|
|
dc2a4c267b | ||
|
|
d5e5a26f5c | ||
|
|
df5ac34c9b | ||
|
|
319dbad795 | ||
|
|
28feb8b1d7 | ||
|
|
f4d898cb92 | ||
|
|
75b5b0fd3c | ||
|
|
6ee3439462 | ||
|
|
4eda5a7ccd | ||
|
|
ad94037516 | ||
|
|
882fb35601 | ||
|
|
48f10a6a20 | ||
|
|
2c35880cbf | ||
|
|
c8af9ced89 | ||
|
|
f89525f8bd | ||
|
|
ad11fbcd00 | ||
|
|
9db661ae63 | ||
|
|
fff5cd50f0 | ||
|
|
b3b50cf503 | ||
|
|
cbebad9586 | ||
|
|
c01023d8f8 | ||
|
|
df610c3cca | ||
|
|
3b7c40bbb3 | ||
|
|
8674f31874 | ||
|
|
b518aad5ac | ||
|
|
12959dec88 | ||
|
|
e381da6a08 | ||
|
|
b004fbfc41 | ||
|
|
8c56ccc5b0 | ||
|
|
c8051eeeed | ||
|
|
5d944b69df | ||
|
|
1fca76c4a8 | ||
|
|
d0e6fcad3f | ||
|
|
d4ba6c4f44 | ||
|
|
35e1b5cbb9 | ||
|
|
f8da3a1b44 | ||
|
|
4ea253220a | ||
|
|
0a5048a56b | ||
|
|
a06652a374 | ||
|
|
86e3991998 | ||
|
|
d9102150cf | ||
|
|
fd08bae1c7 | ||
|
|
4b2af2ede2 | ||
|
|
c6be0b9389 | ||
|
|
6ccdfa074f | ||
|
|
8801029d95 | ||
|
|
5faf6ebadc | ||
|
|
f92d708051 | ||
|
|
76c31c6303 | ||
|
|
cf8ac4dd0e | ||
|
|
879041677c | ||
|
|
cac36365ae | ||
|
|
2c12385344 | ||
|
|
fa217b8775 | ||
|
|
6f7cdde1ba | ||
|
|
da9cc00a56 | ||
|
|
161c90eb8f | ||
|
|
ad5daee004 | ||
|
|
35ea91c111 | ||
|
|
6763490ef6 | ||
|
|
93382f65bb | ||
|
|
190c732c3a | ||
|
|
8bd13edc75 | ||
|
|
98e0774f56 | ||
|
|
c3a44e890d | ||
|
|
a4734d7e30 | ||
|
|
2c267c95e5 | ||
|
|
78f9a6214c | ||
|
|
7ee90a34e5 | ||
|
|
1a6b09afb4 | ||
|
|
c7e158aaa7 | ||
|
|
98c7afd69c | ||
|
|
f3da59e5af | ||
|
|
a17210f387 | ||
|
|
443212d3da | ||
|
|
7a5f60e23f | ||
|
|
7a1d978339 | ||
|
|
6c7ef96354 | ||
|
|
d2e7a37eb4 | ||
|
|
1d8105247a |
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -3,5 +3,7 @@ version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
labels: ["area/build"]
|
||||
schedule:
|
||||
# by default this will be on a monday.
|
||||
interval: "weekly"
|
||||
|
||||
34
.github/runners/README.md
vendored
34
.github/runners/README.md
vendored
@@ -1,24 +1,32 @@
|
||||
# Flux ARM64 GitHub runners
|
||||
|
||||
The Flux ARM64 end-to-end tests run on Equinix instances provisioned with Docker and GitHub self-hosted runners.
|
||||
The Flux ARM64 end-to-end tests run on Equinix Metal instances provisioned with Docker and GitHub self-hosted runners.
|
||||
|
||||
## Current instances
|
||||
|
||||
| Runner | Instance | Region |
|
||||
|---------------|---------------------|--------|
|
||||
| equinix-arm-1 | flux-equinix-arm-01 | AMS1 |
|
||||
| equinix-arm-2 | flux-equinix-arm-01 | AMS1 |
|
||||
| equinix-arm-3 | flux-equinix-arm-01 | AMS1 |
|
||||
| equinix-arm-4 | flux-equinix-arm-02 | DFW2 |
|
||||
| equinix-arm-5 | flux-equinix-arm-02 | DFW2 |
|
||||
| equinix-arm-6 | flux-equinix-arm-02 | DFW2 |
|
||||
| Repository | Runner | Instance | Location |
|
||||
|-----------------------------|------------------|------------------------|---------------|
|
||||
| flux2 | equinix-arm-dc-1 | flux-equinix-arm-dc-01 | Washington DC |
|
||||
| flux2 | equinix-arm-dc-2 | flux-equinix-arm-dc-01 | Washington DC |
|
||||
| flux2 | equinix-arm-da-1 | flux-equinix-arm-da-01 | Dallas |
|
||||
| flux2 | equinix-arm-da-2 | flux-equinix-arm-da-01 | Dallas |
|
||||
| source-controller | equinix-arm-dc-1 | flux-equinix-arm-dc-01 | Washington DC |
|
||||
| source-controller | equinix-arm-da-1 | flux-equinix-arm-da-01 | Dallas |
|
||||
| image-automation-controller | equinix-arm-dc-1 | flux-equinix-arm-dc-01 | Washington DC |
|
||||
| image-automation-controller | equinix-arm-da-1 | flux-equinix-arm-da-01 | Dallas |
|
||||
|
||||
Instance spec:
|
||||
- Ampere Altra Q80-30 80-core processor @ 2.8GHz
|
||||
- 2 x 960GB NVME
|
||||
- 256GB RAM
|
||||
- 2 x 25Gbps
|
||||
|
||||
## Instance setup
|
||||
|
||||
In order to add a new runner to the GitHub Actions pool,
|
||||
first create a server on Equinix with the following configuration:
|
||||
- Type: c2.large.arm
|
||||
- OS: Ubuntu 20.04
|
||||
- Type: `c3.large.arm64`
|
||||
- OS: `Ubuntu 22.04 LTS`
|
||||
|
||||
### Install prerequisites
|
||||
|
||||
@@ -54,14 +62,14 @@ sudo ./prereq.sh
|
||||
|
||||
- Retrieve the GitHub runner token from the repository [settings page](https://github.com/fluxcd/flux2/settings/actions/runners/new?arch=arm64&os=linux)
|
||||
|
||||
- Create 3 directories `runner1`, `runner2`, `runner3`
|
||||
- Create two directories `flux2-01`, `flux2-02`
|
||||
|
||||
- In each dir run:
|
||||
```shell
|
||||
curl -sL https://raw.githubusercontent.com/fluxcd/flux2/main/.github/runners/runner-setup.sh > runner-setup.sh \
|
||||
&& chmod +x ./runner-setup.sh
|
||||
|
||||
./runner-setup.sh equinix-arm-<NUMBER> <TOKEN>
|
||||
./runner-setup.sh equinix-arm-<NUMBER> <TOKEN> <REPO>
|
||||
```
|
||||
|
||||
- Reboot the instance
|
||||
|
||||
12
.github/runners/prereq.sh
vendored
12
.github/runners/prereq.sh
vendored
@@ -18,11 +18,11 @@
|
||||
|
||||
set -eu
|
||||
|
||||
KIND_VERSION=0.14.0
|
||||
KIND_VERSION=0.17.0
|
||||
KUBECTL_VERSION=1.24.0
|
||||
KUSTOMIZE_VERSION=4.5.4
|
||||
HELM_VERSION=3.8.2
|
||||
GITHUB_RUNNER_VERSION=2.291.1
|
||||
KUSTOMIZE_VERSION=4.5.7
|
||||
HELM_VERSION=3.10.1
|
||||
GITHUB_RUNNER_VERSION=2.298.2
|
||||
PACKAGES="apt-transport-https ca-certificates software-properties-common build-essential libssl-dev gnupg lsb-release jq pkg-config"
|
||||
|
||||
# install prerequisites
|
||||
@@ -31,6 +31,10 @@ apt-get update \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# fix Kubernetes DNS resolution
|
||||
rm /etc/resolv.conf
|
||||
cat "/run/systemd/resolve/stub-resolv.conf" | sed '/search/d' > /etc/resolv.conf
|
||||
|
||||
# install docker
|
||||
curl -fsSL https://get.docker.com -o get-docker.sh \
|
||||
&& chmod +x get-docker.sh
|
||||
|
||||
2
.github/runners/runner-setup.sh
vendored
2
.github/runners/runner-setup.sh
vendored
@@ -22,7 +22,7 @@ RUNNER_NAME=$1
|
||||
REPOSITORY_TOKEN=$2
|
||||
REPOSITORY_URL=${3:-https://github.com/fluxcd/flux2}
|
||||
|
||||
GITHUB_RUNNER_VERSION=2.285.1
|
||||
GITHUB_RUNNER_VERSION=2.298.2
|
||||
|
||||
# download runner
|
||||
curl -o actions-runner-linux-arm64.tar.gz -L https://github.com/actions/runner/releases/download/v${GITHUB_RUNNER_VERSION}/actions-runner-linux-arm64-${GITHUB_RUNNER_VERSION}.tar.gz \
|
||||
|
||||
73
.github/workflows/e2e-arm64.yaml
vendored
73
.github/workflows/e2e-arm64.yaml
vendored
@@ -3,7 +3,7 @@ name: e2e-arm64
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main, update-components ]
|
||||
branches: [ main, update-components, e2e-arm64* ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -13,26 +13,87 @@ jobs:
|
||||
# Hosted on Equinix
|
||||
# Docs: https://github.com/fluxcd/flux2/tree/main/.github/runners
|
||||
runs-on: [self-hosted, Linux, ARM64, equinix]
|
||||
strategy:
|
||||
matrix:
|
||||
# Keep this list up-to-date with https://endoflife.date/kubernetes
|
||||
KUBERNETES_VERSION: [ 1.23.13, 1.24.7, 1.25.3 ]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Prepare
|
||||
id: prep
|
||||
run: |
|
||||
echo ::set-output name=CLUSTER::arm64-${GITHUB_SHA:0:7}-$(date +%s)
|
||||
echo ::set-output name=CONTEXT::kind-arm64-${GITHUB_SHA:0:7}-$(date +%s)
|
||||
ID=${GITHUB_SHA:0:7}-${{ matrix.KUBERNETES_VERSION }}-$(date +%s)
|
||||
echo "CLUSTER=arm64-${ID}" >> $GITHUB_OUTPUT
|
||||
- name: Build
|
||||
run: |
|
||||
make build
|
||||
- name: Setup Kubernetes Kind
|
||||
run: |
|
||||
kind create cluster --name ${{ steps.prep.outputs.CLUSTER }} --kubeconfig=/tmp/${{ steps.prep.outputs.CLUSTER }}
|
||||
kind create cluster \
|
||||
--wait 5m \
|
||||
--name ${{ steps.prep.outputs.CLUSTER }} \
|
||||
--kubeconfig=/tmp/${{ steps.prep.outputs.CLUSTER }} \
|
||||
--image=kindest/node:v${{ matrix.KUBERNETES_VERSION }}
|
||||
- name: Run e2e tests
|
||||
run: TEST_KUBECONFIG=/tmp/${{ steps.prep.outputs.CLUSTER }} make e2e
|
||||
- name: Run multi-tenancy tests
|
||||
env:
|
||||
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
|
||||
run: |
|
||||
./bin/flux install
|
||||
./bin/flux create source git flux-system \
|
||||
--interval=15m \
|
||||
--url=https://github.com/fluxcd/flux2-multi-tenancy \
|
||||
--branch=main \
|
||||
--ignore-paths="./clusters/**/flux-system/"
|
||||
./bin/flux create kustomization flux-system \
|
||||
--interval=15m \
|
||||
--source=flux-system \
|
||||
--path=./clusters/staging
|
||||
kubectl -n flux-system wait kustomization/tenants --for=condition=ready --timeout=5m
|
||||
kubectl -n apps wait kustomization/dev-team --for=condition=ready --timeout=1m
|
||||
kubectl -n apps wait helmrelease/podinfo --for=condition=ready --timeout=1m
|
||||
- name: Run monitoring tests
|
||||
# Keep this test in sync with https://fluxcd.io/flux/guides/monitoring/
|
||||
env:
|
||||
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
|
||||
run: |
|
||||
./bin/flux create source git flux-monitoring \
|
||||
--interval=30m \
|
||||
--url=https://github.com/fluxcd/flux2 \
|
||||
--branch=${GITHUB_REF#refs/heads/}
|
||||
./bin/flux create kustomization kube-prometheus-stack \
|
||||
--interval=1h \
|
||||
--prune \
|
||||
--source=flux-monitoring \
|
||||
--path="./manifests/monitoring/kube-prometheus-stack" \
|
||||
--health-check-timeout=5m \
|
||||
--wait
|
||||
./bin/flux create kustomization monitoring-config \
|
||||
--depends-on=kube-prometheus-stack \
|
||||
--interval=1h \
|
||||
--prune=true \
|
||||
--source=flux-monitoring \
|
||||
--path="./manifests/monitoring/monitoring-config" \
|
||||
--health-check-timeout=1m \
|
||||
--wait
|
||||
kubectl -n flux-system wait kustomization/kube-prometheus-stack --for=condition=ready --timeout=5m
|
||||
kubectl -n flux-system wait kustomization/monitoring-config --for=condition=ready --timeout=5m
|
||||
kubectl -n monitoring wait helmrelease/kube-prometheus-stack --for=condition=ready --timeout=1m
|
||||
- name: Debug failure
|
||||
if: failure()
|
||||
env:
|
||||
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
|
||||
run: |
|
||||
kubectl -n flux-system get all
|
||||
kubectl -n flux-system describe po
|
||||
kubectl -n flux-system logs deploy/source-controller
|
||||
kubectl -n flux-system logs deploy/kustomize-controller
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: |
|
||||
|
||||
13
.github/workflows/e2e-azure.yaml
vendored
13
.github/workflows/e2e-azure.yaml
vendored
@@ -15,23 +15,18 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Restore Go cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@58c146cc91c5b9e778e71775dfe9bf1442ad9a12
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go1.18-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go1.18-
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Install libgit2
|
||||
run: |
|
||||
echo "deb http://archive.ubuntu.com/ubuntu/ kinetic universe" | sudo tee -a /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y -t kinetic libgit2-dev=1.3.0+dfsg.1-3ubuntu1
|
||||
- name: Setup Flux CLI
|
||||
run: |
|
||||
make build
|
||||
@@ -44,7 +39,7 @@ jobs:
|
||||
mkdir -p $HOME/.local/bin
|
||||
mv sops-v3.7.1.linux $HOME/.local/bin/sops
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@v2.0.2
|
||||
uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2
|
||||
with:
|
||||
terraform_version: 1.2.8
|
||||
terraform_wrapper: false
|
||||
|
||||
13
.github/workflows/e2e-bootstrap.yaml
vendored
13
.github/workflows/e2e-bootstrap.yaml
vendored
@@ -16,23 +16,24 @@ jobs:
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Restore Go cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@58c146cc91c5b9e778e71775dfe9bf1442ad9a12
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go1.18-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go1.18-
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Setup Kubernetes
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
uses: helm/kind-action@d8ccf8fb623ce1bb360ae2f45f323d9d5c5e9f00 # v1.5.0
|
||||
with:
|
||||
version: v0.16.0
|
||||
image: kindest/node:v1.25.2@sha256:9be91e9e9cdf116809841fc77ebdb8845443c4c72fe5218f3ae9eb57fdb4bace
|
||||
version: v0.17.0
|
||||
cluster_name: kind
|
||||
node_image: kindest/node:v1.25.2
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg//actions/kustomize@main
|
||||
- name: Build
|
||||
|
||||
18
.github/workflows/e2e.yaml
vendored
18
.github/workflows/e2e.yaml
vendored
@@ -20,24 +20,25 @@ jobs:
|
||||
- 5000:5000
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Restore Go cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@58c146cc91c5b9e778e71775dfe9bf1442ad9a12
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go1.18-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go1.18-
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Setup Kubernetes
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
uses: helm/kind-action@d8ccf8fb623ce1bb360ae2f45f323d9d5c5e9f00 # v1.5.0
|
||||
with:
|
||||
version: v0.11.1
|
||||
image: kindest/node:v1.20.7
|
||||
version: v0.17.0
|
||||
cluster_name: kind
|
||||
config: .github/kind/config.yaml # disable KIND-net
|
||||
node_image: kindest/node:v1.23.13
|
||||
- name: Setup Calico for network policy
|
||||
run: |
|
||||
kubectl apply -f https://docs.projectcalico.org/v3.20/manifests/calico.yaml
|
||||
@@ -222,14 +223,13 @@ jobs:
|
||||
/tmp/flux create source git flux-system \
|
||||
--url=https://github.com/fluxcd/flux2-kustomize-helm-example \
|
||||
--branch=main \
|
||||
--ignore-paths="./clusters/**/flux-system/" \
|
||||
--recurse-submodules
|
||||
/tmp/flux create kustomization flux-system \
|
||||
--source=flux-system \
|
||||
--path=./clusters/staging
|
||||
kubectl -n flux-system wait kustomization/infrastructure --for=condition=ready --timeout=5m
|
||||
kubectl -n flux-system wait kustomization/infra-controllers --for=condition=ready --timeout=5m
|
||||
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=5m
|
||||
kubectl -n nginx wait helmrelease/nginx --for=condition=ready --timeout=5m
|
||||
kubectl -n redis wait helmrelease/redis --for=condition=ready --timeout=5m
|
||||
kubectl -n podinfo wait helmrelease/podinfo --for=condition=ready --timeout=5m
|
||||
- name: flux tree
|
||||
run: |
|
||||
|
||||
30
.github/workflows/release.yaml
vendored
30
.github/workflows/release.yaml
vendored
@@ -16,32 +16,32 @@ jobs:
|
||||
packages: write # needed for ghcr access
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Unshallow
|
||||
run: git fetch --prune --unshallow
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@15c905b16b06416d2086efa066dd8e3a35cc7f98 # v2
|
||||
- name: Setup Syft
|
||||
uses: anchore/sbom-action/download-syft@v0
|
||||
uses: anchore/sbom-action/download-syft@07978da4bdb4faa726e52dfc6b1bed63d4b56479 # v0.13.3
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@main
|
||||
uses: sigstore/cosign-installer@9becc617647dfa20ae7b1151972e9b3a2c338a2b # v2.8.1
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg//actions/kustomize@main
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -53,10 +53,8 @@ jobs:
|
||||
- name: Build CRDs
|
||||
run: |
|
||||
kustomize build manifests/crds > all-crds.yaml
|
||||
# Pinned to commit before https://github.com/fluxcd/pkg/pull/189 due to
|
||||
# introduction faulty behavior.
|
||||
- name: Generate OpenAPI JSON schemas from CRDs
|
||||
uses: fluxcd/pkg//actions/crdjsonschema@49e26aa2ee9e734c3233c560253fd9542afe18ae
|
||||
uses: fluxcd/pkg//actions/crdjsonschema@main
|
||||
with:
|
||||
crd: all-crds.yaml
|
||||
output: schemas
|
||||
@@ -75,7 +73,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v3
|
||||
uses: goreleaser/goreleaser-action@9754a253a8673b0ea869c2e863b4e975497efd0c # v3
|
||||
with:
|
||||
version: latest
|
||||
args: release --release-notes=output/notes.md --skip-validate
|
||||
@@ -90,7 +88,7 @@ jobs:
|
||||
id-token: write
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
- name: Setup Flux CLI
|
||||
@@ -101,13 +99,13 @@ jobs:
|
||||
VERSION=$(flux version --client | awk '{ print $NF }')
|
||||
echo ::set-output name=VERSION::${VERSION}
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -135,7 +133,7 @@ jobs:
|
||||
--path="./flux-system" \
|
||||
--source=${{ github.repositoryUrl }} \
|
||||
--revision="${{ github.ref_name }}/${{ github.sha }}"
|
||||
- uses: sigstore/cosign-installer@main
|
||||
- uses: sigstore/cosign-installer@9becc617647dfa20ae7b1151972e9b3a2c338a2b # v2.8.1
|
||||
- name: Sign manifests
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
|
||||
20
.github/workflows/scan.yaml
vendored
20
.github/workflows/scan.yaml
vendored
@@ -17,9 +17,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Run FOSSA scan and upload build data
|
||||
uses: fossa-contrib/fossa-action@v1
|
||||
uses: fossa-contrib/fossa-action@6cffaa064112e1cf9b5798c6224f9487dc1ec316 # v1
|
||||
with:
|
||||
# FOSSA Push-Only API Token
|
||||
fossa-api-key: 5ee8bf422db1471e0bcf2bcb289185de
|
||||
@@ -31,21 +31,21 @@ jobs:
|
||||
security-events: write
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg//actions/kustomize@main
|
||||
- name: Build manifests
|
||||
run: |
|
||||
make cmd/flux/.manifests.done
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
uses: snyk/actions/golang@master
|
||||
uses: snyk/actions/golang@e25b2e6f5658d1bb7a6671b113260f13134cc3af # v0.3.0
|
||||
continue-on-error: true
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
args: --sarif-file-output=snyk.sarif
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
uses: github/codeql-action/upload-sarif@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
|
||||
@@ -56,16 +56,16 @@ jobs:
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2
|
||||
with:
|
||||
languages: go
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2
|
||||
|
||||
6
.github/workflows/update.yaml
vendored
6
.github/workflows/update.yaml
vendored
@@ -18,9 +18,9 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568
|
||||
with:
|
||||
go-version: 1.19.x
|
||||
- name: Update component versions
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@2b011faafdcbc9ceb11414d64d0573f37c774b04 # v4
|
||||
with:
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
commit-message: |
|
||||
|
||||
10
Dockerfile
10
Dockerfile
@@ -1,19 +1,15 @@
|
||||
FROM alpine:3.16 as builder
|
||||
FROM alpine:3.17 as builder
|
||||
|
||||
RUN apk add --no-cache ca-certificates curl
|
||||
|
||||
ARG ARCH=linux/amd64
|
||||
ARG KUBECTL_VER=1.25.3
|
||||
ARG KUBECTL_VER=1.26.1
|
||||
|
||||
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 && \
|
||||
kubectl version --client=true
|
||||
|
||||
FROM alpine:3.16 as flux-cli
|
||||
|
||||
# Create minimal nsswitch.conf file to prioritize the usage of /etc/hosts over DNS queries.
|
||||
# https://github.com/gliderlabs/docker-alpine/issues/367#issuecomment-354316460
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
FROM alpine:3.17 as flux-cli
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
|
||||
@@ -35,6 +35,20 @@ You can download a specific version with:
|
||||
version: 0.32.0
|
||||
```
|
||||
|
||||
You can also authenticate against the GitHub API using GitHub Actions' `GITHUB_TOKEN` secret.
|
||||
|
||||
For more information, please [read about the GitHub token secret](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret).
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
This is useful if you are seeing failures on shared runners, those failures are usually API limits being hit.
|
||||
|
||||
### Automate Flux updates
|
||||
|
||||
Example workflow for updating Flux's components generated with `flux bootstrap --path=clusters/production`:
|
||||
@@ -52,7 +66,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Check for updates
|
||||
@@ -62,9 +76,9 @@ jobs:
|
||||
--export > ./clusters/production/flux-system/gotk-components.yaml
|
||||
|
||||
VERSION="$(flux -v)"
|
||||
echo "::set-output name=flux_version::$VERSION"
|
||||
echo "flux_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: update-flux
|
||||
@@ -120,18 +134,25 @@ jobs:
|
||||
flux tag artifact $OCI_REPO:$(git rev-parse --short HEAD) --tag staging
|
||||
```
|
||||
|
||||
Example workflow for publishing Kubernetes manifests bundled as OCI artifacts to Docker Hub:
|
||||
### Push and sign Kubernetes manifests to container registries
|
||||
|
||||
Example workflow for publishing Kubernetes manifests bundled as OCI artifacts
|
||||
which are signed with Cosign and GitHub OIDC:
|
||||
|
||||
```yaml
|
||||
name: push-artifact-production
|
||||
name: push-sign-artifact
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
permissions:
|
||||
packages: write # needed for ghcr.io access
|
||||
id-token: write # needed for keyless signing
|
||||
|
||||
env:
|
||||
OCI_REPO: "oci://docker.io/my-org/app-config"
|
||||
OCI_REPO: "oci://ghcr.io/my-org/manifests/${{ github.event.repository.name }}"
|
||||
|
||||
jobs:
|
||||
kubernetes:
|
||||
@@ -141,23 +162,24 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Login to Docker Hub
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@main
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Generate manifests
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Push and sign manifests
|
||||
run: |
|
||||
kustomize build ./manifests/production > ./deploy/app.yaml
|
||||
- name: Push manifests
|
||||
run: |
|
||||
flux push artifact $OCI_REPO:$(git tag --points-at HEAD) \
|
||||
--path="./deploy" \
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git tag --points-at HEAD)/$(git rev-parse HEAD)"
|
||||
- name: Deploy manifests to production
|
||||
run: |
|
||||
flux tag artifact $OCI_REPO:$(git tag --points-at HEAD) --tag production
|
||||
digest_url=$(flux push artifact \
|
||||
$OCI_REPO:$(git rev-parse --short HEAD) \
|
||||
--path="./manifests" \
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git branch --show-current)/$(git rev-parse HEAD)" |\
|
||||
jq -r '. | .repository + "@" + .digest')
|
||||
|
||||
cosign sign $digest_url
|
||||
```
|
||||
|
||||
### End-to-end testing
|
||||
@@ -177,7 +199,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Setup Kubernetes Kind
|
||||
|
||||
@@ -15,6 +15,9 @@ inputs:
|
||||
bindir:
|
||||
description: "Optional location of the Flux binary. Will not use sudo if set. Updates System Path."
|
||||
required: false
|
||||
token:
|
||||
description: "GitHub Token used to authentication against the API (generally only needed to prevent quota limit errors)"
|
||||
required: false
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
@@ -23,20 +26,29 @@ runs:
|
||||
run: |
|
||||
ARCH=${{ inputs.arch }}
|
||||
VERSION=${{ inputs.version }}
|
||||
TOKEN=${{ inputs.token }}
|
||||
|
||||
if [ -z $VERSION ]; then
|
||||
VERSION=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest -sL | grep tag_name | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
|
||||
if [ -z "${VERSION}" ]; then
|
||||
if [ -n "${TOKEN}" ]; then
|
||||
VERSION_SLUG=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest --silent --location --header "Authorization: token ${TOKEN}" | grep tag_name)
|
||||
else
|
||||
# With no GITHUB_TOKEN you will experience occasional failures due to rate limiting
|
||||
# Ref: https://github.com/fluxcd/flux2/issues/3509#issuecomment-1400820992
|
||||
VERSION_SLUG=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest --silent --location | grep tag_name)
|
||||
fi
|
||||
|
||||
VERSION=$(echo "${VERSION_SLUG}" | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
|
||||
fi
|
||||
|
||||
BIN_URL="https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_${ARCH}.tar.gz"
|
||||
curl -sL ${BIN_URL} -o /tmp/flux.tar.gz
|
||||
curl --silent --fail --location "${BIN_URL}" --output /tmp/flux.tar.gz
|
||||
mkdir -p /tmp/flux
|
||||
tar -C /tmp/flux/ -zxvf /tmp/flux.tar.gz
|
||||
- name: "Copy Flux binary to execute location"
|
||||
shell: bash
|
||||
run: |
|
||||
BINDIR=${{ inputs.bindir }}
|
||||
if [ -z $BINDIR ]; then
|
||||
if [ -z "${BINDIR}" ]; then
|
||||
sudo cp /tmp/flux/flux /usr/local/bin
|
||||
else
|
||||
cp /tmp/flux/flux "${BINDIR}"
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
// notificationv1.Alert
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
// notificationv1.Provider
|
||||
|
||||
@@ -22,13 +22,13 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/flags"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git/gogit"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/provider"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
@@ -128,7 +128,9 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Manifest base
|
||||
if ver, err := getVersion(bootstrapArgs.version); err == nil {
|
||||
if ver, err := getVersion(bootstrapArgs.version); err != nil {
|
||||
return err
|
||||
} else {
|
||||
bootstrapArgs.version = ver
|
||||
}
|
||||
manifestsBase, err := buildEmbeddedManifestBase()
|
||||
@@ -171,10 +173,17 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("failed to create temporary working dir: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
gitClient := gogit.New(tmpDir, &http.BasicAuth{
|
||||
Username: user,
|
||||
Password: bitbucketToken,
|
||||
})
|
||||
|
||||
clientOpts := []gogit.ClientOption{gogit.WithDiskStorage(), gogit.WithFallbackToDefaultKnownHosts()}
|
||||
gitClient, err := gogit.NewClient(tmpDir, &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Username: user,
|
||||
Password: bitbucketToken,
|
||||
CAFile: caBundle,
|
||||
}, clientOpts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create a Git client: %w", err)
|
||||
}
|
||||
|
||||
// Install manifest config
|
||||
installOptions := install.Options{
|
||||
@@ -212,19 +221,18 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
|
||||
secretOpts.Username = bServerArgs.username
|
||||
}
|
||||
secretOpts.Password = bitbucketToken
|
||||
|
||||
if bootstrapArgs.caFile != "" {
|
||||
secretOpts.CAFilePath = bootstrapArgs.caFile
|
||||
}
|
||||
secretOpts.CAFile = caBundle
|
||||
} else {
|
||||
keypair, err := sourcesecret.LoadKeyPairFromPath(bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretOpts.Keypair = keypair
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
||||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||
secretOpts.ECDSACurve = bootstrapArgs.keyECDSACurve.Curve
|
||||
secretOpts.SSHHostname = bServerArgs.hostname
|
||||
|
||||
if bootstrapArgs.privateKeyFile != "" {
|
||||
secretOpts.PrivateKeyPath = bootstrapArgs.privateKeyFile
|
||||
}
|
||||
secretOpts.SSHHostname = bServerArgs.hostname
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
secretOpts.SSHHostname = bootstrapArgs.sshHostname
|
||||
}
|
||||
@@ -243,19 +251,24 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Bootstrap config
|
||||
|
||||
bootstrapOpts := []bootstrap.GitProviderOption{
|
||||
bootstrap.WithProviderRepository(bServerArgs.owner, bServerArgs.repository, bServerArgs.personal),
|
||||
bootstrap.WithBranch(bootstrapArgs.branch),
|
||||
bootstrap.WithBootstrapTransportType("https"),
|
||||
bootstrap.WithAuthor(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithSignature(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
|
||||
bootstrap.WithProviderTeamPermissions(mapTeamSlice(bServerArgs.teams, bServerDefaultPermission)),
|
||||
bootstrap.WithReadWriteKeyPermissions(bServerArgs.readWriteKey),
|
||||
bootstrap.WithKubeconfig(kubeconfigArgs, kubeclientOptions),
|
||||
bootstrap.WithLogger(logger),
|
||||
bootstrap.WithCABundle(caBundle),
|
||||
bootstrap.WithGitCommitSigning(bootstrapArgs.gpgKeyRingPath, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname))
|
||||
|
||||
@@ -24,9 +24,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -34,11 +31,12 @@ import (
|
||||
"github.com/fluxcd/flux2/internal/flags"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git/gogit"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/sourcesecret"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/sync"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
)
|
||||
|
||||
var bootstrapGitCmd = &cobra.Command{
|
||||
@@ -62,6 +60,12 @@ command will perform an upgrade if needed.`,
|
||||
|
||||
# Run bootstrap for a Git repository with a private key and password
|
||||
flux bootstrap git --url=ssh://git@example.com/repository.git --private-key-file=<path/to/private.key> --password=<password>
|
||||
|
||||
# Run bootstrap for a Git repository on AWS CodeCommit
|
||||
flux bootstrap git --url=ssh://<SSH-Key-ID>@git-codecommit.<region>.amazonaws.com/v1/repos/<repository> --private-key-file=<path/to/private.key> --password=<SSH-passphrase>
|
||||
|
||||
# Run bootstrap for a Git repository on Azure Devops
|
||||
flux bootstrap git --url=ssh://git@ssh.dev.azure.com/v3/<org>/<project>/<repository> --ssh-key-algorithm=rsa --ssh-rsa-bits=4096
|
||||
`,
|
||||
RunE: bootstrapGitCmdRun,
|
||||
}
|
||||
@@ -116,9 +120,22 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gitAuth, err := transportForURL(repositoryURL)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
if strings.Contains(repositoryURL.Hostname(), "git-codecommit") && strings.Contains(repositoryURL.Hostname(), "amazonaws.com") {
|
||||
if repositoryURL.Scheme == string(git.SSH) {
|
||||
if repositoryURL.User == nil {
|
||||
return fmt.Errorf("invalid AWS CodeCommit url: ssh username should be specified in the url")
|
||||
}
|
||||
if repositoryURL.User.Username() == git.DefaultPublicKeyAuthUser {
|
||||
return fmt.Errorf("invalid AWS CodeCommit url: ssh username should be the SSH key ID for the provided private key")
|
||||
}
|
||||
if bootstrapArgs.privateKeyFile == "" {
|
||||
return fmt.Errorf("private key file is required for bootstrapping against AWS CodeCommit using ssh")
|
||||
}
|
||||
}
|
||||
if repositoryURL.Scheme == string(git.HTTPS) && !bootstrapArgs.tokenAuth {
|
||||
return fmt.Errorf("--token-auth=true must be specified for using a HTTPS AWS CodeCommit url")
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
@@ -130,7 +147,9 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Manifest base
|
||||
if ver, err := getVersion(bootstrapArgs.version); err == nil {
|
||||
if ver, err := getVersion(bootstrapArgs.version); err != nil {
|
||||
return err
|
||||
} else {
|
||||
bootstrapArgs.version = ver
|
||||
}
|
||||
manifestsBase, err := buildEmbeddedManifestBase()
|
||||
@@ -145,7 +164,28 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("failed to create temporary working dir: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
gitClient := gogit.New(tmpDir, gitAuth)
|
||||
|
||||
var caBundle []byte
|
||||
if bootstrapArgs.caFile != "" {
|
||||
var err error
|
||||
caBundle, err = os.ReadFile(bootstrapArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
authOpts, err := getAuthOpts(repositoryURL, caBundle)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create authentication options for %s: %w", repositoryURL.String(), err)
|
||||
}
|
||||
|
||||
clientOpts := []gogit.ClientOption{gogit.WithDiskStorage(), gogit.WithFallbackToDefaultKnownHosts()}
|
||||
if gitArgs.insecureHttpAllowed {
|
||||
clientOpts = append(clientOpts, gogit.WithInsecureCredentialsOverHTTP())
|
||||
}
|
||||
gitClient, err := gogit.NewClient(tmpDir, authOpts, clientOpts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create a Git client: %w", err)
|
||||
}
|
||||
|
||||
// Install manifest config
|
||||
installOptions := install.Options{
|
||||
@@ -179,10 +219,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.tokenAuth {
|
||||
secretOpts.Username = gitArgs.username
|
||||
secretOpts.Password = gitArgs.password
|
||||
|
||||
if bootstrapArgs.caFile != "" {
|
||||
secretOpts.CAFilePath = bootstrapArgs.caFile
|
||||
}
|
||||
secretOpts.CAFile = caBundle
|
||||
|
||||
// Remove port of the given host when not syncing over HTTP/S to not assume port for protocol
|
||||
// This _might_ be overwritten later on by e.g. --ssh-hostname
|
||||
@@ -213,9 +250,12 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
repositoryURL.Host = bootstrapArgs.sshHostname
|
||||
}
|
||||
if bootstrapArgs.privateKeyFile != "" {
|
||||
secretOpts.PrivateKeyPath = bootstrapArgs.privateKeyFile
|
||||
|
||||
keypair, err := sourcesecret.LoadKeyPairFromPath(bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretOpts.Keypair = keypair
|
||||
|
||||
// Configure last as it depends on the config above.
|
||||
secretOpts.SSHHostname = repositoryURL.Host
|
||||
@@ -235,26 +275,21 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
}
|
||||
|
||||
var caBundle []byte
|
||||
if bootstrapArgs.caFile != "" {
|
||||
var err error
|
||||
caBundle, err = os.ReadFile(bootstrapArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Bootstrap config
|
||||
bootstrapOpts := []bootstrap.GitOption{
|
||||
bootstrap.WithRepositoryURL(gitArgs.url),
|
||||
bootstrap.WithBranch(bootstrapArgs.branch),
|
||||
bootstrap.WithAuthor(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithSignature(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
|
||||
bootstrap.WithKubeconfig(kubeconfigArgs, kubeclientOptions),
|
||||
bootstrap.WithPostGenerateSecretFunc(promptPublicKey),
|
||||
bootstrap.WithLogger(logger),
|
||||
bootstrap.WithCABundle(caBundle),
|
||||
bootstrap.WithGitCommitSigning(bootstrapArgs.gpgKeyRingPath, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
|
||||
// Setup bootstrapper with constructed configs
|
||||
@@ -267,30 +302,47 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return bootstrap.Run(ctx, b, manifestsBase, installOptions, secretOpts, syncOpts, rootArgs.pollInterval, rootArgs.timeout)
|
||||
}
|
||||
|
||||
// transportForURL constructs a transport.AuthMethod based on the scheme
|
||||
// getAuthOpts retruns a AuthOptions based on the scheme
|
||||
// of the given URL and the configured flags. If the protocol equals
|
||||
// "ssh" but no private key is configured, authentication using the local
|
||||
// SSH-agent is attempted.
|
||||
func transportForURL(u *url.URL) (transport.AuthMethod, error) {
|
||||
func getAuthOpts(u *url.URL, caBundle []byte) (*git.AuthOptions, error) {
|
||||
switch u.Scheme {
|
||||
case "http":
|
||||
if !gitArgs.insecureHttpAllowed {
|
||||
return nil, fmt.Errorf("scheme http is insecure, pass --allow-insecure-http=true to allow it")
|
||||
}
|
||||
return &http.BasicAuth{
|
||||
Username: gitArgs.username,
|
||||
Password: gitArgs.password,
|
||||
return &git.AuthOptions{
|
||||
Transport: git.HTTP,
|
||||
Username: gitArgs.username,
|
||||
Password: gitArgs.password,
|
||||
}, nil
|
||||
case "https":
|
||||
return &http.BasicAuth{
|
||||
Username: gitArgs.username,
|
||||
Password: gitArgs.password,
|
||||
return &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Username: gitArgs.username,
|
||||
Password: gitArgs.password,
|
||||
CAFile: caBundle,
|
||||
}, nil
|
||||
case "ssh":
|
||||
if bootstrapArgs.privateKeyFile != "" {
|
||||
return ssh.NewPublicKeysFromFile(u.User.Username(), bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||
authOpts := &git.AuthOptions{
|
||||
Transport: git.SSH,
|
||||
Username: u.User.Username(),
|
||||
Password: gitArgs.password,
|
||||
}
|
||||
return nil, nil
|
||||
if bootstrapArgs.privateKeyFile != "" {
|
||||
pk, err := os.ReadFile(bootstrapArgs.privateKeyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kh, err := sourcesecret.ScanHostKey(u.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authOpts.Identity = pk
|
||||
authOpts.KnownHosts = kh
|
||||
}
|
||||
return authOpts, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("scheme %q is not supported", u.Scheme)
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/flags"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git/gogit"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/provider"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
@@ -132,7 +132,9 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Manifest base
|
||||
if ver, err := getVersion(bootstrapArgs.version); err == nil {
|
||||
if ver, err := getVersion(bootstrapArgs.version); err != nil {
|
||||
return err
|
||||
} else {
|
||||
bootstrapArgs.version = ver
|
||||
}
|
||||
manifestsBase, err := buildEmbeddedManifestBase()
|
||||
@@ -161,16 +163,22 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Lazy go-git repository
|
||||
tmpDir, err := manifestgen.MkdirTempAbs("", "flux-bootstrap-")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temporary working dir: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
gitClient := gogit.New(tmpDir, &http.BasicAuth{
|
||||
Username: githubArgs.owner,
|
||||
Password: ghToken,
|
||||
})
|
||||
|
||||
clientOpts := []gogit.ClientOption{gogit.WithDiskStorage(), gogit.WithFallbackToDefaultKnownHosts()}
|
||||
gitClient, err := gogit.NewClient(tmpDir, &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Username: githubArgs.owner,
|
||||
Password: ghToken,
|
||||
CAFile: caBundle,
|
||||
}, clientOpts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create a Git client: %w", err)
|
||||
}
|
||||
|
||||
// Install manifest config
|
||||
installOptions := install.Options{
|
||||
@@ -204,16 +212,13 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.tokenAuth {
|
||||
secretOpts.Username = "git"
|
||||
secretOpts.Password = ghToken
|
||||
|
||||
if bootstrapArgs.caFile != "" {
|
||||
secretOpts.CAFilePath = bootstrapArgs.caFile
|
||||
}
|
||||
secretOpts.CAFile = caBundle
|
||||
} else {
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
||||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||
secretOpts.ECDSACurve = bootstrapArgs.keyECDSACurve.Curve
|
||||
secretOpts.SSHHostname = githubArgs.hostname
|
||||
|
||||
secretOpts.SSHHostname = githubArgs.hostname
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
secretOpts.SSHHostname = bootstrapArgs.sshHostname
|
||||
}
|
||||
@@ -232,19 +237,23 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Bootstrap config
|
||||
bootstrapOpts := []bootstrap.GitProviderOption{
|
||||
bootstrap.WithProviderRepository(githubArgs.owner, githubArgs.repository, githubArgs.personal),
|
||||
bootstrap.WithBranch(bootstrapArgs.branch),
|
||||
bootstrap.WithBootstrapTransportType("https"),
|
||||
bootstrap.WithAuthor(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithSignature(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
|
||||
bootstrap.WithProviderTeamPermissions(mapTeamSlice(githubArgs.teams, ghDefaultPermission)),
|
||||
bootstrap.WithReadWriteKeyPermissions(githubArgs.readWriteKey),
|
||||
bootstrap.WithKubeconfig(kubeconfigArgs, kubeclientOptions),
|
||||
bootstrap.WithLogger(logger),
|
||||
bootstrap.WithCABundle(caBundle),
|
||||
bootstrap.WithGitCommitSigning(bootstrapArgs.gpgKeyRingPath, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname))
|
||||
|
||||
@@ -24,13 +24,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/flags"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git/gogit"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/provider"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
@@ -136,7 +136,9 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// Manifest base
|
||||
if ver, err := getVersion(bootstrapArgs.version); err == nil {
|
||||
if ver, err := getVersion(bootstrapArgs.version); err != nil {
|
||||
return err
|
||||
} else {
|
||||
bootstrapArgs.version = ver
|
||||
}
|
||||
manifestsBase, err := buildEmbeddedManifestBase()
|
||||
@@ -178,10 +180,17 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("failed to create temporary working dir: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
gitClient := gogit.New(tmpDir, &http.BasicAuth{
|
||||
Username: gitlabArgs.owner,
|
||||
Password: glToken,
|
||||
})
|
||||
|
||||
clientOpts := []gogit.ClientOption{gogit.WithDiskStorage(), gogit.WithFallbackToDefaultKnownHosts()}
|
||||
gitClient, err := gogit.NewClient(tmpDir, &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Username: gitlabArgs.owner,
|
||||
Password: glToken,
|
||||
CAFile: caBundle,
|
||||
}, clientOpts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create a Git client: %w", err)
|
||||
}
|
||||
|
||||
// Install manifest config
|
||||
installOptions := install.Options{
|
||||
@@ -215,19 +224,18 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if bootstrapArgs.tokenAuth {
|
||||
secretOpts.Username = "git"
|
||||
secretOpts.Password = glToken
|
||||
|
||||
if bootstrapArgs.caFile != "" {
|
||||
secretOpts.CAFilePath = bootstrapArgs.caFile
|
||||
}
|
||||
secretOpts.CAFile = caBundle
|
||||
} else {
|
||||
keypair, err := sourcesecret.LoadKeyPairFromPath(bootstrapArgs.privateKeyFile, gitArgs.password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretOpts.Keypair = keypair
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
|
||||
secretOpts.RSAKeyBits = int(bootstrapArgs.keyRSABits)
|
||||
secretOpts.ECDSACurve = bootstrapArgs.keyECDSACurve.Curve
|
||||
secretOpts.SSHHostname = gitlabArgs.hostname
|
||||
|
||||
if bootstrapArgs.privateKeyFile != "" {
|
||||
secretOpts.PrivateKeyPath = bootstrapArgs.privateKeyFile
|
||||
}
|
||||
secretOpts.SSHHostname = gitlabArgs.hostname
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
secretOpts.SSHHostname = bootstrapArgs.sshHostname
|
||||
}
|
||||
@@ -246,19 +254,23 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
|
||||
RecurseSubmodules: bootstrapArgs.recurseSubmodules,
|
||||
}
|
||||
|
||||
entityList, err := bootstrap.LoadEntityListFromPath(bootstrapArgs.gpgKeyRingPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Bootstrap config
|
||||
bootstrapOpts := []bootstrap.GitProviderOption{
|
||||
bootstrap.WithProviderRepository(gitlabArgs.owner, gitlabArgs.repository, gitlabArgs.personal),
|
||||
bootstrap.WithBranch(bootstrapArgs.branch),
|
||||
bootstrap.WithBootstrapTransportType("https"),
|
||||
bootstrap.WithAuthor(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithSignature(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
|
||||
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
|
||||
bootstrap.WithProviderTeamPermissions(mapTeamSlice(gitlabArgs.teams, glDefaultPermission)),
|
||||
bootstrap.WithReadWriteKeyPermissions(gitlabArgs.readWriteKey),
|
||||
bootstrap.WithKubeconfig(kubeconfigArgs, kubeclientOptions),
|
||||
bootstrap.WithLogger(logger),
|
||||
bootstrap.WithCABundle(caBundle),
|
||||
bootstrap.WithGitCommitSigning(bootstrapArgs.gpgKeyRingPath, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID),
|
||||
}
|
||||
if bootstrapArgs.sshHostname != "" {
|
||||
bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname))
|
||||
|
||||
@@ -17,7 +17,10 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -54,7 +57,7 @@ var excludeOCI = append(strings.Split(sourceignore.ExcludeVCS, ","), strings.Spl
|
||||
var buildArtifactArgs buildArtifactFlags
|
||||
|
||||
func init() {
|
||||
buildArtifactCmd.Flags().StringVar(&buildArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.")
|
||||
buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.path, "path", "p", "", "Path to the directory where the Kubernetes manifests are located.")
|
||||
buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.output, "output", "o", "artifact.tgz", "Path to where the artifact tgz file should be written.")
|
||||
buildArtifactCmd.Flags().StringSliceVar(&buildArtifactArgs.ignorePaths, "ignore-paths", excludeOCI, "set paths to ignore in .gitignore format")
|
||||
|
||||
@@ -66,18 +69,48 @@ func buildArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("invalid path %q", buildArtifactArgs.path)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(buildArtifactArgs.path); err != nil {
|
||||
return fmt.Errorf("invalid path '%s', must point to an existing directory or file", buildArtifactArgs.path)
|
||||
path := buildArtifactArgs.path
|
||||
var err error
|
||||
if buildArtifactArgs.path == "-" {
|
||||
path, err = saveReaderToFile(os.Stdin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(path)
|
||||
}
|
||||
|
||||
logger.Actionf("building artifact from %s", buildArtifactArgs.path)
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return fmt.Errorf("invalid path '%s', must point to an existing directory or file", path)
|
||||
}
|
||||
|
||||
logger.Actionf("building artifact from %s", path)
|
||||
|
||||
ociClient := oci.NewLocalClient()
|
||||
if err := ociClient.Build(buildArtifactArgs.output, buildArtifactArgs.path, buildArtifactArgs.ignorePaths); err != nil {
|
||||
if err := ociClient.Build(buildArtifactArgs.output, path, buildArtifactArgs.ignorePaths); err != nil {
|
||||
return fmt.Errorf("bulding artifact failed, error: %w", err)
|
||||
}
|
||||
|
||||
logger.Successf("artifact created at %s", buildArtifactArgs.output)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func saveReaderToFile(reader io.Reader) (string, error) {
|
||||
b, err := io.ReadAll(bufio.NewReader(reader))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b = bytes.TrimRight(b, "\r\n")
|
||||
f, err := os.CreateTemp("", "*.yaml")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to create temp dir for stdin")
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
if _, err := f.Write(b); err != nil {
|
||||
return "", fmt.Errorf("error writing stdin to file: %w", err)
|
||||
}
|
||||
|
||||
return f.Name(), nil
|
||||
}
|
||||
|
||||
70
cmd/flux/build_artifact_test.go
Normal file
70
cmd/flux/build_artifact_test.go
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright 2022 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 (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func Test_saveReaderToFile(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
testString := `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: myapp
|
||||
data:
|
||||
foo: bar`
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
string string
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "yaml",
|
||||
string: testString,
|
||||
},
|
||||
{
|
||||
name: "yaml with carriage return",
|
||||
string: testString + "\r\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tmpFile, err := saveReaderToFile(strings.NewReader(tt.string))
|
||||
g.Expect(err).To(BeNil())
|
||||
|
||||
defer os.Remove(tmpFile)
|
||||
|
||||
b, err := os.ReadFile(tmpFile)
|
||||
if tt.expectErr {
|
||||
g.Expect(err).To(Not(BeNil()))
|
||||
return
|
||||
}
|
||||
|
||||
g.Expect(err).To(BeNil())
|
||||
g.Expect(string(b)).To(BeEquivalentTo(testString))
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,11 @@ It is possible to specify a Flux kustomization file using --kustomization-file.`
|
||||
flux build kustomization my-app --path ./path/to/local/manifests
|
||||
|
||||
# Build using a local flux kustomization file
|
||||
flux build kustomization my-app --path ./path/to/local/manifests --kustomization-file ./path/to/local/my-app.yaml`,
|
||||
flux build kustomization my-app --path ./path/to/local/manifests --kustomization-file ./path/to/local/my-app.yaml
|
||||
|
||||
# Build in dry-run mode without connecting to the cluster.
|
||||
# Note that variable substitutions from Secrets and ConfigMaps are skipped in dry-run mode.
|
||||
flux build kustomization my-app --path ./path/to/local/manifests --kustomization-file ./path/to/local/my-app.yaml --dry-run`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
RunE: buildKsCmdRun,
|
||||
}
|
||||
@@ -48,6 +52,7 @@ flux build kustomization my-app --path ./path/to/local/manifests --kustomization
|
||||
type buildKsFlags struct {
|
||||
kustomizationFile string
|
||||
path string
|
||||
dryRun bool
|
||||
}
|
||||
|
||||
var buildKsArgs buildKsFlags
|
||||
@@ -55,10 +60,11 @@ var buildKsArgs buildKsFlags
|
||||
func init() {
|
||||
buildKsCmd.Flags().StringVar(&buildKsArgs.path, "path", "", "Path to the manifests location.")
|
||||
buildKsCmd.Flags().StringVar(&buildKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.")
|
||||
buildKsCmd.Flags().BoolVar(&buildKsArgs.dryRun, "dry-run", false, "Dry run mode.")
|
||||
buildCmd.AddCommand(buildKsCmd)
|
||||
}
|
||||
|
||||
func buildKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("%s name is required", kustomizationType.humanKind)
|
||||
}
|
||||
@@ -72,13 +78,32 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("invalid resource path %q", buildKsArgs.path)
|
||||
}
|
||||
|
||||
if buildKsArgs.dryRun && buildKsArgs.kustomizationFile == "" {
|
||||
return fmt.Errorf("dry-run mode requires a kustomization file")
|
||||
}
|
||||
|
||||
if buildKsArgs.kustomizationFile != "" {
|
||||
if fs, err := os.Stat(buildKsArgs.kustomizationFile); os.IsNotExist(err) || fs.IsDir() {
|
||||
return fmt.Errorf("invalid kustomization file %q", buildKsArgs.kustomizationFile)
|
||||
}
|
||||
}
|
||||
|
||||
builder, err := build.NewBuilder(kubeconfigArgs, kubeclientOptions, name, buildKsArgs.path, build.WithTimeout(rootArgs.timeout), build.WithKustomizationFile(buildKsArgs.kustomizationFile))
|
||||
var builder *build.Builder
|
||||
if buildKsArgs.dryRun {
|
||||
builder, err = build.NewBuilder(name, buildKsArgs.path,
|
||||
build.WithTimeout(rootArgs.timeout),
|
||||
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
||||
build.WithDryRun(buildKsArgs.dryRun),
|
||||
build.WithNamespace(*kubeconfigArgs.Namespace),
|
||||
)
|
||||
} else {
|
||||
builder, err = build.NewBuilder(name, buildKsArgs.path,
|
||||
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
||||
build.WithTimeout(rootArgs.timeout),
|
||||
build.WithKustomizationFile(buildKsArgs.kustomizationFile),
|
||||
)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -142,6 +142,12 @@ spec:
|
||||
resultFile: "./testdata/build-kustomization/podinfo-with-var-substitution-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
{
|
||||
name: "build deployment and configmap with var substitution in dry-run mode",
|
||||
args: "build kustomization podinfo --kustomization-file ./testdata/build-kustomization/podinfo.yaml --path ./testdata/build-kustomization/var-substitution --dry-run",
|
||||
resultFile: "./testdata/build-kustomization/podinfo-with-var-substitution-result.yaml",
|
||||
assertFunc: "assertGoldenTemplateFile",
|
||||
},
|
||||
}
|
||||
|
||||
tmpl := map[string]string{
|
||||
|
||||
@@ -242,8 +242,9 @@ func crdsCheck() bool {
|
||||
}
|
||||
|
||||
for _, crd := range list.Items {
|
||||
if len(crd.Status.StoredVersions) > 0 {
|
||||
logger.Successf(crd.Name + "/" + crd.Status.StoredVersions[0])
|
||||
versions := crd.Status.StoredVersions
|
||||
if len(versions) > 0 {
|
||||
logger.Successf(crd.Name + "/" + versions[len(versions)-1])
|
||||
} else {
|
||||
ok = false
|
||||
logger.Failuref("no stored versions for %s", crd.Name)
|
||||
|
||||
@@ -34,12 +34,12 @@ To configure your powershell shell to load completions for each session add to y
|
||||
Windows:
|
||||
|
||||
cd "$env:USERPROFILE\Documents\WindowsPowerShell\Modules"
|
||||
flux completion >> flux-completion.ps1
|
||||
flux completion powershell >> flux-completion.ps1
|
||||
|
||||
Linux:
|
||||
|
||||
cd "${XDG_CONFIG_HOME:-"$HOME/.config/"}/powershell/modules"
|
||||
flux completion >> flux-completions.ps1`,
|
||||
flux completion powershell >> flux-completions.ps1`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
rootCmd.GenPowerShellCompletion(os.Stdout)
|
||||
},
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"crypto/elliptic"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -135,8 +136,12 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
switch u.Scheme {
|
||||
case "ssh":
|
||||
keypair, err := sourcesecret.LoadKeyPairFromPath(secretGitArgs.privateKeyFile, secretGitArgs.password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts.Keypair = keypair
|
||||
opts.SSHHostname = u.Host
|
||||
opts.PrivateKeyPath = secretGitArgs.privateKeyFile
|
||||
opts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(secretGitArgs.keyAlgorithm)
|
||||
opts.RSAKeyBits = int(secretGitArgs.rsaBits)
|
||||
opts.ECDSACurve = secretGitArgs.ecdsaCurve.Curve
|
||||
@@ -147,7 +152,13 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
opts.Username = secretGitArgs.username
|
||||
opts.Password = secretGitArgs.password
|
||||
opts.CAFilePath = secretGitArgs.caFile
|
||||
if secretGitArgs.caFile != "" {
|
||||
caBundle, err := os.ReadFile(secretGitArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
opts.CAFile = caBundle
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -74,15 +76,34 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
caBundle := []byte{}
|
||||
if secretHelmArgs.caFile != "" {
|
||||
var err error
|
||||
caBundle, err = os.ReadFile(secretHelmArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var certFile, keyFile []byte
|
||||
if secretHelmArgs.certFile != "" && secretHelmArgs.keyFile != "" {
|
||||
if certFile, err = os.ReadFile(secretHelmArgs.certFile); err != nil {
|
||||
return fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if keyFile, err = os.ReadFile(secretHelmArgs.keyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
opts := sourcesecret.Options{
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Labels: labels,
|
||||
Username: secretHelmArgs.username,
|
||||
Password: secretHelmArgs.password,
|
||||
CAFilePath: secretHelmArgs.caFile,
|
||||
CertFilePath: secretHelmArgs.certFile,
|
||||
KeyFilePath: secretHelmArgs.keyFile,
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Labels: labels,
|
||||
Username: secretHelmArgs.username,
|
||||
Password: secretHelmArgs.password,
|
||||
CAFile: caBundle,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
}
|
||||
secret, err := sourcesecret.Generate(opts)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,6 +18,8 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
@@ -73,13 +75,32 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
caBundle := []byte{}
|
||||
if secretTLSArgs.caFile != "" {
|
||||
var err error
|
||||
caBundle, err = os.ReadFile(secretTLSArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var certFile, keyFile []byte
|
||||
if secretTLSArgs.certFile != "" && secretTLSArgs.keyFile != "" {
|
||||
if certFile, err = os.ReadFile(secretTLSArgs.certFile); err != nil {
|
||||
return fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if keyFile, err = os.ReadFile(secretTLSArgs.keyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
opts := sourcesecret.Options{
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Labels: labels,
|
||||
CAFilePath: secretTLSArgs.caFile,
|
||||
CertFilePath: secretTLSArgs.certFile,
|
||||
KeyFilePath: secretTLSArgs.keyFile,
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Labels: labels,
|
||||
CAFile: caBundle,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
}
|
||||
secret, err := sourcesecret.Generate(opts)
|
||||
if err != nil {
|
||||
|
||||
@@ -259,16 +259,26 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
switch u.Scheme {
|
||||
case "ssh":
|
||||
keypair, err := sourcesecret.LoadKeyPairFromPath(sourceGitArgs.privateKeyFile, sourceGitArgs.password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretOpts.Keypair = keypair
|
||||
secretOpts.SSHHostname = u.Host
|
||||
secretOpts.PrivateKeyPath = sourceGitArgs.privateKeyFile
|
||||
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(sourceGitArgs.keyAlgorithm)
|
||||
secretOpts.RSAKeyBits = int(sourceGitArgs.keyRSABits)
|
||||
secretOpts.ECDSACurve = sourceGitArgs.keyECDSACurve.Curve
|
||||
secretOpts.Password = sourceGitArgs.password
|
||||
case "https":
|
||||
if sourceGitArgs.caFile != "" {
|
||||
caBundle, err := os.ReadFile(sourceGitArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
secretOpts.CAFile = caBundle
|
||||
}
|
||||
secretOpts.Username = sourceGitArgs.username
|
||||
secretOpts.Password = sourceGitArgs.password
|
||||
secretOpts.CAFilePath = sourceGitArgs.caFile
|
||||
case "http":
|
||||
logger.Warningf("insecure configuration: credentials configured for an HTTP URL")
|
||||
secretOpts.Username = sourceGitArgs.username
|
||||
|
||||
@@ -168,6 +168,25 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
caBundle := []byte{}
|
||||
if sourceHelmArgs.caFile != "" {
|
||||
var err error
|
||||
caBundle, err = os.ReadFile(sourceHelmArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var certFile, keyFile []byte
|
||||
if sourceHelmArgs.certFile != "" && sourceHelmArgs.keyFile != "" {
|
||||
if certFile, err = os.ReadFile(sourceHelmArgs.certFile); err != nil {
|
||||
return fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if keyFile, err = os.ReadFile(sourceHelmArgs.keyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Generatef("generating HelmRepository source")
|
||||
if sourceHelmArgs.secretRef == "" {
|
||||
secretName := fmt.Sprintf("helm-%s", name)
|
||||
@@ -176,9 +195,9 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Username: sourceHelmArgs.username,
|
||||
Password: sourceHelmArgs.password,
|
||||
CertFilePath: sourceHelmArgs.certFile,
|
||||
KeyFilePath: sourceHelmArgs.keyFile,
|
||||
CAFilePath: sourceHelmArgs.caFile,
|
||||
CAFile: caBundle,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
|
||||
}
|
||||
secret, err := sourcesecret.Generate(secretOpts)
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var deleteAlertCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var deleteAlertProviderCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var deleteReceiverCmd = &cobra.Command{
|
||||
|
||||
@@ -77,12 +77,21 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
var builder *build.Builder
|
||||
var err error
|
||||
var (
|
||||
builder *build.Builder
|
||||
err error
|
||||
)
|
||||
if diffKsArgs.progressBar {
|
||||
builder, err = build.NewBuilder(kubeconfigArgs, kubeclientOptions, name, diffKsArgs.path, build.WithTimeout(rootArgs.timeout), build.WithKustomizationFile(diffKsArgs.kustomizationFile), build.WithProgressBar())
|
||||
builder, err = build.NewBuilder(name, diffKsArgs.path,
|
||||
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
||||
build.WithTimeout(rootArgs.timeout),
|
||||
build.WithKustomizationFile(diffKsArgs.kustomizationFile),
|
||||
build.WithProgressBar())
|
||||
} else {
|
||||
builder, err = build.NewBuilder(kubeconfigArgs, kubeclientOptions, name, diffKsArgs.path, build.WithTimeout(rootArgs.timeout), build.WithKustomizationFile(diffKsArgs.kustomizationFile))
|
||||
builder, err = build.NewBuilder(name, diffKsArgs.path,
|
||||
build.WithClientConfig(kubeconfigArgs, kubeclientOptions),
|
||||
build.WithTimeout(rootArgs.timeout),
|
||||
build.WithKustomizationFile(diffKsArgs.kustomizationFile))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -97,7 +97,7 @@ func TestDiffKustomization(t *testing.T) {
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
|
||||
b, _ := build.NewBuilder(kubeconfigArgs, kubeclientOptions, "podinfo", "")
|
||||
b, _ := build.NewBuilder("podinfo", "", build.WithClientConfig(kubeconfigArgs, kubeclientOptions))
|
||||
|
||||
resourceManager, err := b.Manager()
|
||||
if err != nil {
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var exportAlertCmd = &cobra.Command{
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var exportAlertProviderCmd = &cobra.Command{
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var exportReceiverCmd = &cobra.Command{
|
||||
|
||||
@@ -163,9 +163,16 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if get.list.len() == 0 {
|
||||
if len(args) > 0 {
|
||||
logger.Failuref("%s object '%s' not found in '%s' namespace", get.kind, args[0], *kubeconfigArgs.Namespace)
|
||||
logger.Failuref("%s object '%s' not found in %s namespace",
|
||||
get.kind,
|
||||
args[0],
|
||||
namespaceNameOrAny(getArgs.allNamespaces, *kubeconfigArgs.Namespace),
|
||||
)
|
||||
} else if !getAll {
|
||||
logger.Failuref("no %s objects found in %s namespace", get.kind, *kubeconfigArgs.Namespace)
|
||||
logger.Failuref("no %s objects found in %s namespace",
|
||||
get.kind,
|
||||
namespaceNameOrAny(getArgs.allNamespaces, *kubeconfigArgs.Namespace),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -192,6 +199,13 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func namespaceNameOrAny(allNamespaces bool, namespaceName string) string {
|
||||
if allNamespaces {
|
||||
return "any"
|
||||
}
|
||||
return fmt.Sprintf("%q", namespaceName)
|
||||
}
|
||||
|
||||
func getRowsToPrint(getAll bool, list summarisable) ([][]string, error) {
|
||||
noFilter := true
|
||||
var conditionType, conditionStatus string
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var getAlertCmd = &cobra.Command{
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var getAlertProviderCmd = &cobra.Command{
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var getAllCmd = &cobra.Command{
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var getReceiverCmd = &cobra.Command{
|
||||
|
||||
@@ -18,12 +18,15 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/flags"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
reg "github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
oci "github.com/fluxcd/pkg/oci/client"
|
||||
)
|
||||
@@ -40,6 +43,21 @@ The command can read the credentials from '~/.docker/config.json' but they can a
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git branch --show-current)/$(git rev-parse HEAD)"
|
||||
|
||||
# Push and sign artifact with cosign
|
||||
digest_url = $(flux push artifact \
|
||||
oci://ghcr.io/org/config/app:$(git rev-parse --short HEAD) \
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git branch --show-current)/$(git rev-parse HEAD)" \
|
||||
--path="./path/to/local/manifest.yaml" \
|
||||
--output json | \
|
||||
jq -r '. | .repository + "@" + .digest')
|
||||
cosign sign $digest_url
|
||||
|
||||
# Push manifests passed into stdin to GHCR
|
||||
kustomize build . | flux push artifact oci://ghcr.io/org/config/app:$(git rev-parse --short HEAD) -p - \
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git branch --show-current)/$(git rev-parse HEAD)"
|
||||
|
||||
# Push single manifest file to GHCR using the short Git SHA as the OCI artifact tag
|
||||
echo $GITHUB_PAT | docker login ghcr.io --username flux --password-stdin
|
||||
flux push artifact oci://ghcr.io/org/config/app:$(git rev-parse --short HEAD) \
|
||||
@@ -80,6 +98,7 @@ type pushArtifactFlags struct {
|
||||
creds string
|
||||
provider flags.SourceOCIProvider
|
||||
ignorePaths []string
|
||||
output string
|
||||
}
|
||||
|
||||
var pushArtifactArgs = newPushArtifactFlags()
|
||||
@@ -97,6 +116,8 @@ func init() {
|
||||
pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.creds, "creds", "", "credentials for OCI registry in the format <username>[:<password>] if --provider is generic")
|
||||
pushArtifactCmd.Flags().Var(&pushArtifactArgs.provider, "provider", pushArtifactArgs.provider.Description())
|
||||
pushArtifactCmd.Flags().StringSliceVar(&pushArtifactArgs.ignorePaths, "ignore-paths", excludeOCI, "set paths to ignore in .gitignore format")
|
||||
pushArtifactCmd.Flags().StringVarP(&pushArtifactArgs.output, "output", "o", "",
|
||||
"the format in which the artifact digest should be printed, can be 'json' or 'yaml'")
|
||||
|
||||
pushCmd.AddCommand(pushArtifactCmd)
|
||||
}
|
||||
@@ -124,8 +145,18 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(pushArtifactArgs.path); err != nil {
|
||||
return fmt.Errorf("invalid path '%s', must point to an existing directory or file", buildArtifactArgs.path)
|
||||
path := pushArtifactArgs.path
|
||||
if pushArtifactArgs.path == "-" {
|
||||
path, err = saveReaderToFile(os.Stdin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(path)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return fmt.Errorf("invalid path '%s', must point to an existing directory or file: %w", path, err)
|
||||
}
|
||||
|
||||
meta := oci.Metadata{
|
||||
@@ -157,14 +188,54 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
logger.Actionf("pushing artifact to %s", url)
|
||||
if pushArtifactArgs.output == "" {
|
||||
logger.Actionf("pushing artifact to %s", url)
|
||||
}
|
||||
|
||||
digest, err := ociClient.Push(ctx, url, pushArtifactArgs.path, meta, pushArtifactArgs.ignorePaths)
|
||||
digestURL, err := ociClient.Push(ctx, url, path, meta, pushArtifactArgs.ignorePaths)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pushing artifact failed: %w", err)
|
||||
}
|
||||
|
||||
logger.Successf("artifact successfully pushed to %s", digest)
|
||||
digest, err := reg.NewDigest(digestURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("artifact digest parsing failed: %w", err)
|
||||
}
|
||||
|
||||
tag, err := reg.NewTag(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("artifact tag parsing failed: %w", err)
|
||||
}
|
||||
|
||||
info := struct {
|
||||
URL string `json:"url"`
|
||||
Repository string `json:"repository"`
|
||||
Tag string `json:"tag"`
|
||||
Digest string `json:"digest"`
|
||||
}{
|
||||
URL: fmt.Sprintf("oci://%s", digestURL),
|
||||
Repository: digest.Repository.Name(),
|
||||
Tag: tag.TagStr(),
|
||||
Digest: digest.DigestStr(),
|
||||
}
|
||||
|
||||
switch pushArtifactArgs.output {
|
||||
case "json":
|
||||
marshalled, err := json.MarshalIndent(&info, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("artifact digest JSON conversion failed: %w", err)
|
||||
}
|
||||
marshalled = append(marshalled, "\n"...)
|
||||
rootCmd.Print(string(marshalled))
|
||||
case "yaml":
|
||||
marshalled, err := yaml.Marshal(&info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("artifact digest YAML conversion failed: %w", err)
|
||||
}
|
||||
rootCmd.Print(string(marshalled))
|
||||
default:
|
||||
logger.Successf("artifact successfully pushed to %s", digestURL)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
// notificationv1.Receiver
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
"k8s.io/client-go/util/retry"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
@@ -111,7 +111,7 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
logger.Successf("%s annotated", reconcile.kind)
|
||||
|
||||
if reconcile.kind == v1beta1.AlertKind || reconcile.kind == v1beta1.ReceiverKind {
|
||||
if reconcile.kind == notificationv1.AlertKind || reconcile.kind == notificationv1.ReceiverKind {
|
||||
if err = wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
|
||||
isReconcileReady(ctx, kubeClient, namespacedName, reconcile.object)); err != nil {
|
||||
return err
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var reconcileAlertCmd = &cobra.Command{
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var resumeAlertCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var resumeReceiverCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var suspendAlertCmd = &cobra.Command{
|
||||
|
||||
@@ -19,7 +19,7 @@ package main
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var suspendReceiverCmd = &cobra.Command{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: autoscaling/v2beta2
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: podinfo
|
||||
|
||||
@@ -77,7 +77,7 @@ spec:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
---
|
||||
apiVersion: autoscaling/v2beta2
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -77,7 +77,7 @@ spec:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
---
|
||||
apiVersion: autoscaling/v2beta2
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: autoscaling/v2beta2
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: podinfo
|
||||
|
||||
2
cmd/flux/testdata/export/alert.yaml
vendored
2
cmd/flux/testdata/export/alert.yaml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta2
|
||||
kind: Alert
|
||||
metadata:
|
||||
name: flux-system
|
||||
|
||||
6
cmd/flux/testdata/export/objects.yaml
vendored
6
cmd/flux/testdata/export/objects.yaml
vendored
@@ -4,7 +4,7 @@ kind: Namespace
|
||||
metadata:
|
||||
name: {{ .fluxns }}
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta2
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: slack
|
||||
@@ -14,7 +14,7 @@ spec:
|
||||
channel: 'A channel with spacess'
|
||||
address: https://hooks.slack.com/services/mock
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta2
|
||||
kind: Alert
|
||||
metadata:
|
||||
name: flux-system
|
||||
@@ -97,7 +97,7 @@ spec:
|
||||
interval: 5m
|
||||
prune: true
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta2
|
||||
kind: Receiver
|
||||
metadata:
|
||||
name: flux-system
|
||||
|
||||
2
cmd/flux/testdata/export/provider.yaml
vendored
2
cmd/flux/testdata/export/provider.yaml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta2
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: slack
|
||||
|
||||
2
cmd/flux/testdata/export/receiver.yaml
vendored
2
cmd/flux/testdata/export/receiver.yaml
vendored
@@ -1,5 +1,5 @@
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta1
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta2
|
||||
kind: Receiver
|
||||
metadata:
|
||||
name: flux-system
|
||||
|
||||
@@ -26,18 +26,21 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/tree"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/cli-utils/pkg/object"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/tree"
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
)
|
||||
|
||||
var treeKsCmd = &cobra.Command{
|
||||
@@ -262,6 +265,7 @@ func getHelmReleaseInventory(ctx context.Context, objectKey client.ObjectKey, ku
|
||||
b = b2
|
||||
}
|
||||
|
||||
// extract objects from Helm storage
|
||||
var rls hrStorage
|
||||
if err := json.Unmarshal(b, &rls); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
|
||||
@@ -272,5 +276,52 @@ func getHelmReleaseInventory(ctx context.Context, objectKey client.ObjectKey, ku
|
||||
return nil, fmt.Errorf("failed to read the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
|
||||
}
|
||||
|
||||
return object.UnstructuredSetToObjMetadataSet(objects), nil
|
||||
// set the namespace on namespaced objects
|
||||
for _, obj := range objects {
|
||||
if obj.GetNamespace() == "" {
|
||||
if isNamespaced, _ := utils.IsAPINamespaced(obj, kubeClient.Scheme(), kubeClient.RESTMapper()); isNamespaced {
|
||||
if hr.Spec.TargetNamespace != "" {
|
||||
obj.SetNamespace(hr.Spec.TargetNamespace)
|
||||
} else {
|
||||
obj.SetNamespace(hr.GetNamespace())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result := object.UnstructuredSetToObjMetadataSet(objects)
|
||||
|
||||
// search for CRDs managed by the HelmRelease if installing or upgrading CRDs is enabled in spec
|
||||
if (hr.Spec.Install != nil && len(hr.Spec.Install.CRDs) > 0 && hr.Spec.Install.CRDs != helmv2.Skip) ||
|
||||
(hr.Spec.Upgrade != nil && len(hr.Spec.Upgrade.CRDs) > 0 && hr.Spec.Upgrade.CRDs != helmv2.Skip) {
|
||||
selector := client.MatchingLabels{
|
||||
fmt.Sprintf("%s/name", helmv2.GroupVersion.Group): hr.GetName(),
|
||||
fmt.Sprintf("%s/namespace", helmv2.GroupVersion.Group): hr.GetNamespace(),
|
||||
}
|
||||
crdKind := "CustomResourceDefinition"
|
||||
var list apiextensionsv1.CustomResourceDefinitionList
|
||||
if err := kubeClient.List(ctx, &list, selector); err == nil {
|
||||
for _, crd := range list.Items {
|
||||
found := false
|
||||
for _, r := range result {
|
||||
if r.Name == crd.GetName() && r.GroupKind.Kind == crdKind {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
result = append(result, object.ObjMetadata{
|
||||
Name: crd.GetName(),
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: apiextensionsv1.GroupName,
|
||||
Kind: crdKind,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
176
go.mod
176
go.mod
@@ -3,52 +3,53 @@ module github.com/fluxcd/flux2
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220930113650-c6815a8c17ad
|
||||
github.com/Masterminds/semver/v3 v3.2.0
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230127202215-f7f10de891d5
|
||||
github.com/cyphar/filepath-securejoin v0.2.3
|
||||
github.com/distribution/distribution/v3 v3.0.0-20221021092657-c47a966fded8
|
||||
github.com/fluxcd/go-git-providers v0.9.0
|
||||
github.com/fluxcd/helm-controller/api v0.26.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.26.1
|
||||
github.com/fluxcd/image-reflector-controller/api v0.22.1
|
||||
github.com/fluxcd/kustomize-controller/api v0.30.0
|
||||
github.com/fluxcd/notification-controller/api v0.28.0
|
||||
github.com/fluxcd/pkg/apis/meta v0.17.0
|
||||
github.com/fluxcd/pkg/kustomize v0.8.0
|
||||
github.com/fluxcd/pkg/oci v0.14.0
|
||||
github.com/fluxcd/pkg/runtime v0.22.0
|
||||
github.com/fluxcd/pkg/sourceignore v0.2.0
|
||||
github.com/fluxcd/pkg/ssa v0.21.0
|
||||
github.com/fluxcd/pkg/ssh v0.6.0
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230131081513-cf87e8d07e8d
|
||||
github.com/fluxcd/go-git-providers v0.13.0
|
||||
github.com/fluxcd/go-git/v5 v5.0.0-20221219190809-2e5c9d01cfc4
|
||||
github.com/fluxcd/helm-controller/api v0.29.0
|
||||
github.com/fluxcd/image-automation-controller/api v0.29.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.24.0
|
||||
github.com/fluxcd/kustomize-controller/api v0.33.0
|
||||
github.com/fluxcd/notification-controller/api v0.31.0
|
||||
github.com/fluxcd/pkg/apis/meta v0.19.0
|
||||
github.com/fluxcd/pkg/git v0.8.0
|
||||
github.com/fluxcd/pkg/git/gogit v0.5.0
|
||||
github.com/fluxcd/pkg/kustomize v0.13.0
|
||||
github.com/fluxcd/pkg/oci v0.18.0
|
||||
github.com/fluxcd/pkg/runtime v0.27.0
|
||||
github.com/fluxcd/pkg/sourceignore v0.3.0
|
||||
github.com/fluxcd/pkg/ssa v0.23.0
|
||||
github.com/fluxcd/pkg/ssh v0.7.0
|
||||
github.com/fluxcd/pkg/untar v0.2.0
|
||||
github.com/fluxcd/pkg/version v0.2.0
|
||||
github.com/fluxcd/source-controller/api v0.31.0
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/fluxcd/source-controller/api v0.34.0
|
||||
github.com/gonvenience/bunt v1.3.4
|
||||
github.com/gonvenience/ytbx v1.4.4
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/go-containerregistry v0.12.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/google/go-containerregistry v0.13.0
|
||||
github.com/homeport/dyff v1.5.6
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/mattn/go-shellwords v1.0.12
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/onsi/gomega v1.22.1
|
||||
github.com/onsi/gomega v1.26.0
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
|
||||
github.com/spf13/cobra v1.6.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/theckman/yacspin v0.13.12
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/term v0.1.0
|
||||
k8s.io/api v0.25.3
|
||||
k8s.io/apiextensions-apiserver v0.25.3
|
||||
k8s.io/apimachinery v0.25.3
|
||||
k8s.io/cli-runtime v0.25.3
|
||||
k8s.io/client-go v0.25.3
|
||||
k8s.io/kubectl v0.25.3
|
||||
sigs.k8s.io/cli-utils v0.33.0
|
||||
sigs.k8s.io/controller-runtime v0.13.0
|
||||
golang.org/x/crypto v0.5.0
|
||||
golang.org/x/term v0.4.0
|
||||
k8s.io/api v0.26.1
|
||||
k8s.io/apiextensions-apiserver v0.26.1
|
||||
k8s.io/apimachinery v0.26.1
|
||||
k8s.io/cli-runtime v0.26.1
|
||||
k8s.io/client-go v0.26.1
|
||||
k8s.io/kubectl v0.26.1
|
||||
sigs.k8s.io/cli-utils v0.34.0
|
||||
sigs.k8s.io/controller-runtime v0.14.2
|
||||
sigs.k8s.io/kustomize/api v0.12.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.9
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
@@ -61,24 +62,29 @@ replace golang.org/x/text => golang.org/x/text v0.4.0
|
||||
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.99.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect
|
||||
github.com/BurntSushi/toml v1.0.0 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.105 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.28 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.18.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.2 // indirect
|
||||
github.com/aws/smithy-go v1.13.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd // indirect
|
||||
@@ -87,7 +93,7 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/cloudflare/circl v1.1.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.12.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
@@ -98,28 +104,28 @@ require (
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect
|
||||
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/drone/envsubst v1.0.3 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.1.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.6.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.8.0 // indirect
|
||||
github.com/fluxcd/pkg/tar v0.2.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||
github.com/go-git/go-git/v5 v5.4.2 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||
github.com/go-openapi/swag v0.21.1 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/gomodule/redigo v1.8.2 // indirect
|
||||
@@ -127,9 +133,9 @@ require (
|
||||
github.com/gonvenience/term v1.0.2 // indirect
|
||||
github.com/gonvenience/text v1.0.7 // indirect
|
||||
github.com/gonvenience/wrap v1.1.2 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/gnostic v0.6.9 // indirect
|
||||
github.com/google/go-github/v47 v47.0.0 // indirect
|
||||
github.com/google/go-github/v48 v48.2.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
@@ -137,17 +143,18 @@ require (
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
@@ -156,13 +163,13 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/hashstructure v1.1.0 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
@@ -170,35 +177,36 @@ require (
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pjbgf/sha1cd v0.2.3 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.13.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday v1.6.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/skeema/knownhosts v1.1.0 // indirect
|
||||
github.com/texttheater/golang-levenshtein v1.0.1 // indirect
|
||||
github.com/vbatts/tar-split v0.11.2 // indirect
|
||||
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect
|
||||
github.com/xanzy/go-gitlab v0.73.1 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
github.com/xanzy/go-gitlab v0.77.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // indirect
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 // indirect
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/net v0.1.0 // indirect
|
||||
golang.org/x/oauth2 v0.1.0 // indirect
|
||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 // indirect
|
||||
golang.org/x/mod v0.7.0 // indirect
|
||||
golang.org/x/net v0.5.0 // indirect
|
||||
golang.org/x/oauth2 v0.2.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.4.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
@@ -206,10 +214,10 @@ require (
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/component-base v0.25.3 // indirect
|
||||
k8s.io/klog/v2 v2.80.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
|
||||
k8s.io/component-base v0.26.1 // indirect
|
||||
k8s.io/klog/v2 v2.90.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20221110221610-a28e98eb7c70 // indirect
|
||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
)
|
||||
|
||||
525
go.sum
525
go.sum
@@ -13,20 +13,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
||||
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||
cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY=
|
||||
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
@@ -45,49 +31,35 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20220903154154-e8044f6e4c72 h1:1sCHCT0xRr7UArrI1WJxsl9S8QeYdf0fmuGIl2xb7YI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.3 h1:8LoU8N2lIUzkmstvwXvVfniMZlFbesfT2AmA1aqvRr8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.3/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 h1:Oj853U9kG+RLTCQXpjvOnrv0WaZHxgmZz1TlLywgOPY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
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.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A=
|
||||
github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
|
||||
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.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
|
||||
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220930113650-c6815a8c17ad h1:QeeqI2zxxgZVe11UrYFXXx6gVxPVF40ygekjBzEg4XY=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20220930113650-c6815a8c17ad/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230127202215-f7f10de891d5 h1:Fu4D/i1HBoWql9xVIfW50Kohujz+T3xXPV60JVb3Fao=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230127202215-f7f10de891d5/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
@@ -97,13 +69,38 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
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/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aws/aws-sdk-go v1.44.105 h1:UUwoD1PRKIj3ltrDUYTDQj5fOTK3XsnqolLpRTMmSEM=
|
||||
github.com/aws/aws-sdk-go v1.44.105/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.3 h1:shN7NlnVzvDUgPQ+1rLMSxY8OWRNDRYtiqe0p/PgrhY=
|
||||
github.com/aws/aws-sdk-go-v2 v1.17.3/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.10 h1:Znce11DWswdh+5kOsIp+QaNfY9igp1QUN+fZHCKmeCI=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.10/go.mod h1:VATKco+pl+Qe1WW+RzvZTlPPe/09Gg9+vM0ZXsqb16k=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.10 h1:T4Y39IhelTLg1f3xiKJssThnFxsndS8B6OnmcXtKK+8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.10/go.mod h1:tqAm4JmQaShel+Qi38hmd1QglSnnxaYt50k/9yGQzzc=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.21 h1:j9wi1kQ8b+e0FBVHxCqCGo4kxDU175hoDHcWAi0sauU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.21/go.mod h1:ugwW57Z5Z48bpvUyZuaPy4Kv+vEfJWnIrky7RmkBvJg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27 h1:I3cakv2Uy1vNmmhRQmFptYDxOvBnwCdNwyw63N0RaRU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27/go.mod h1:a1/UpzeyBBerajpnP5nGZa9mGzsBn5cOKxm6NWQsvoI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21 h1:5NbbMrIzmUn/TXFqAle6mgrH5m9cOvMLRGL7pnG8tRE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21/go.mod h1:+Gxn8jYn5k9ebfHEqlhrMirFjSW0v0C9fI+KN5vk2kE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.28 h1:KeTxcGdNnQudb46oOl4d90f2I33DF/c6q3RnZAmvQdQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.28/go.mod h1:yRZVr/iT0AqyHeep00SZ4YfBAKojXz08w3XMBscdi0c=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.18.1 h1:fZNQcqqyAcb34XZ6uNuDlmKIaZKRGdoXYfK5WLRjBbQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.18.1/go.mod h1:9yGOFsa2OcdyePojE89xNGtdBusTyc8ocjpiuFtFc0g=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.21 h1:5C6XgTViSb0bunmU57b3CT+MhxULqHH2721FVA+/kDM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.21/go.mod h1:lRToEJsn+DRA9lW4O9L9+/3hjTkUzlzyzHqn8MTds5k=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.0 h1:/2gzjhQowRLarkkBOGPXSRnb8sQ2RVsjdG1C/UliK/c=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.0/go.mod h1:wo/B7uUm/7zw/dWhBJ4FXuw1sySU5lyIhVg1Bu2yL9A=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.0 h1:Jfly6mRxk2ZOSlbCvZfKNS7TukSx1mIzhSsqZ/IGSZI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.0/go.mod h1:TZSH7xLO7+phDtViY/KUp9WGCJMQkLJ/VpgkTFd5gh8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.2 h1:J/4wIaGInCEYCGhTSruxCxeoA5cy91a+JT7cHFKFSHQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.2/go.mod h1:+lGbb3+1ugwKrNTWcf2RT05Xmp543B06zDFTwiTLp7I=
|
||||
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
|
||||
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
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=
|
||||
@@ -134,10 +131,10 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cloudflare/circl v1.3.1 h1:4OVCZRL62ijwEwxnF6I7hLwxvIYi3VaZt8TflkqtrtA=
|
||||
github.com/cloudflare/circl v1.3.1/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0=
|
||||
@@ -147,14 +144,13 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20221021092657-c47a966fded8 h1:zuxvqNfQKyGNH3a1yFh1ofD4Y7ycgdwQhHX6QRH+Cwo=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20221021092657-c47a966fded8/go.mod h1:6rIc5NMSjXjjnwzWWy3HAm9gDBu+X7aCzL8VrHIKgxM=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230131081513-cf87e8d07e8d h1:q1rtMRnFYz9NAVV4k2iL/w5mNkur3TJysH3Phi9Ns08=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230131081513-cf87e8d07e8d/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI=
|
||||
github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c=
|
||||
github.com/docker/cli v20.10.20+incompatible h1:lWQbHSHUFs7KraSN2jOJK7zbMS2jNCHI4mt4xUFUVQ4=
|
||||
github.com/docker/cli v20.10.20+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
@@ -171,86 +167,96 @@ github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHz
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0=
|
||||
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
|
||||
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
|
||||
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0=
|
||||
github.com/emicklei/go-restful/v3 v3.10.0 h1:X4gma4HM7hFm6WMeAsTfqA0GOfdNoCzBIkHGoRLGXuM=
|
||||
github.com/emicklei/go-restful/v3 v3.10.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
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/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
|
||||
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
|
||||
github.com/fluxcd/go-git-providers v0.9.0 h1:iiiKe3dzRCgVkjEi8rfpvaWTZwuGRfb3RJFhjSNz+Uc=
|
||||
github.com/fluxcd/go-git-providers v0.9.0/go.mod h1:GcaDVP9RlamLKJp25Nwi7X5t0MyZV3FY+qy1GiRdbtk=
|
||||
github.com/fluxcd/helm-controller/api v0.26.0 h1:UCod+R1Oct2jg5cXHlVBC57Jy01lMdpl9MA+8UPogvY=
|
||||
github.com/fluxcd/helm-controller/api v0.26.0/go.mod h1:Ef7OnSHwMub7Z3F+UNe8p/mblOQ2aSQjCWSRfAqG2FA=
|
||||
github.com/fluxcd/image-automation-controller/api v0.26.1 h1:+9ISIrgvrqPhJcEKrhlvocu29CEwSn6kjAvsG9XlTXY=
|
||||
github.com/fluxcd/image-automation-controller/api v0.26.1/go.mod h1:stNr/kLPGu3DELAN0da7NBAjDPrA3TWZn818bAxBiW8=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.22.1 h1:n4G1UamjfG4aV12x5lMEB4tj9DLCQvUo4KAGZMmdzVs=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.22.1/go.mod h1:cZ8uWRExmULpIeQtoY5FmoPFfvpgMOZbR9qjyIgB2L0=
|
||||
github.com/fluxcd/kustomize-controller/api v0.30.0 h1:kOl2wGX1yqz080Ej58WHnWUCGEs6PNo+6b74FA6rJL8=
|
||||
github.com/fluxcd/kustomize-controller/api v0.30.0/go.mod h1:MisuQ92Y8CR0jR9jCWStvVIYiK5PiDBEq3rfyVRr5sg=
|
||||
github.com/fluxcd/notification-controller/api v0.28.0 h1:7dRUoKgVatGB235iOl0Z2PXOAoHdbpvmCPnNoy+ljnc=
|
||||
github.com/fluxcd/notification-controller/api v0.28.0/go.mod h1:USY8Mz7K9uoIn0cNBqq2WTix2cbzpFi9kbs4CMBjB+w=
|
||||
github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
|
||||
github.com/fluxcd/go-git-providers v0.13.0 h1:VTuOMfatoqkCrEUOX5CVpSMiA1TIs0ioLh3LPmFCqiw=
|
||||
github.com/fluxcd/go-git-providers v0.13.0/go.mod h1:VEItGJ67Xc/7Cadh/oPMPUimXv75R0XqHFtF3J4tIdE=
|
||||
github.com/fluxcd/go-git/v5 v5.0.0-20221219190809-2e5c9d01cfc4 h1:Gm5sGGk+/Wq6RhX4xpCZ2IqjDp5XkjlhENaAuAlpdKc=
|
||||
github.com/fluxcd/go-git/v5 v5.0.0-20221219190809-2e5c9d01cfc4/go.mod h1:raWgfUV7lDQVXp4QXUaeNNJkRVKz97UQuF+0kdY7Vmo=
|
||||
github.com/fluxcd/helm-controller/api v0.29.0 h1:aoyI2fQNR/8rmUCz6l4kqQzgS3oAvP3/K6qP/uKk2C0=
|
||||
github.com/fluxcd/helm-controller/api v0.29.0/go.mod h1:BXivPOvBtSKRmcs2HdAtlR5hlC0UGU5Zg847KmtXvkQ=
|
||||
github.com/fluxcd/image-automation-controller/api v0.29.0 h1:86g4NgPCzfBaE4CRKc2EtyaVrEdbFVs81KLOz4vHZjA=
|
||||
github.com/fluxcd/image-automation-controller/api v0.29.0/go.mod h1:mmRgP6i2TzEQUzIIjay0G7fPb6Y11Qzw1CTD7aj1zMc=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.24.0 h1:F0X+IaRSPAWeV5ZDzeqw7hKbq74AmxLSU/SwdXCcc3c=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.24.0/go.mod h1:F4l0tBvVk2XAKoRt4xzZmj+XmuaD6fc44n8waAEZMjE=
|
||||
github.com/fluxcd/kustomize-controller/api v0.33.0 h1:ELTDIBC9dYaQjwIOtQxXAX2S4ydD6VQbmgf9p8wxIpE=
|
||||
github.com/fluxcd/kustomize-controller/api v0.33.0/go.mod h1:6dVUIhT3Dge4Fyljv/qILYygwUTpAXl5IDjoOFLebfE=
|
||||
github.com/fluxcd/notification-controller/api v0.31.0 h1:KcxsVwL1DU1BGro0raAt5+FwHCgGJwNsa915DdrAehs=
|
||||
github.com/fluxcd/notification-controller/api v0.31.0/go.mod h1:K+Jxxbj8NRI9L2+NjV7T0TqUtq5NspZaH2fidHbguZ0=
|
||||
github.com/fluxcd/pkg/apis/acl v0.1.0 h1:EoAl377hDQYL3WqanWCdifauXqXbMyFuK82NnX6pH4Q=
|
||||
github.com/fluxcd/pkg/apis/acl v0.1.0/go.mod h1:zfEZzz169Oap034EsDhmCAGgnWlcWmIObZjYMusoXS8=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.6.0 h1:Afxv3Uv+xiuettzqm3sP0ceWikDZTfHdHtLv6u2nFM8=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.6.0/go.mod h1:iY0zSpK6eUiPfNt/yR6g0q/wQP+wH+Ax/L7KBOx5x2M=
|
||||
github.com/fluxcd/pkg/apis/meta v0.17.0 h1:Y2dfo1syHZDb9Mexjr2SWdcj1FnxnRXm015hEnhl6wU=
|
||||
github.com/fluxcd/pkg/apis/meta v0.17.0/go.mod h1:GrOVzWXiu22XjLNgLLe2EBYhQPqZetes5SIADb4bmHE=
|
||||
github.com/fluxcd/pkg/kustomize v0.8.0 h1:8AdEvp6y38ISZzoi0H82Si5zkmLXClbeX10W7HevB00=
|
||||
github.com/fluxcd/pkg/kustomize v0.8.0/go.mod h1:zGtCZF6V3hMWcf46SqrQc10fS9yUlKzi2UcFUeabDAE=
|
||||
github.com/fluxcd/pkg/oci v0.14.0 h1:KwjOf2OSB1bZvNEwDfp+FbOrK0fMcSYA01AJEc671mQ=
|
||||
github.com/fluxcd/pkg/oci v0.14.0/go.mod h1:TH7ru7YlX5L3xihbdnIgYVWXsOqrYcJIci/Mq4MgWbo=
|
||||
github.com/fluxcd/pkg/runtime v0.22.0 h1:4YV/An41b+OGdSWDogwFfHr22CEE/in+lBLEK0fr1yc=
|
||||
github.com/fluxcd/pkg/runtime v0.22.0/go.mod h1:Cm6jIhltzXIM3CRRY6SFASDn+z2m/1yPqOWwD73c3io=
|
||||
github.com/fluxcd/pkg/sourceignore v0.2.0 h1:ooNbIkfxqNB+KKiY4AU+/DxwzjIKIOWBRK1As5QFlug=
|
||||
github.com/fluxcd/pkg/sourceignore v0.2.0/go.mod h1:m9/q+YLMNSWjXns1n/5q3ucwzSSddti+D6ExbNaCo6s=
|
||||
github.com/fluxcd/pkg/ssa v0.21.0 h1:aeoTohPNf5x7jQjHidyLJAOHw3EyHOQoQN3mN2i+4cc=
|
||||
github.com/fluxcd/pkg/ssa v0.21.0/go.mod h1:jumyhUbEMDnduN7anSlKfxl2fEoyeyv+Ta5hWCbxI5Q=
|
||||
github.com/fluxcd/pkg/ssh v0.6.0 h1:yRJ866obXCo0JseJCqlGKtF8cumioPcwIC6kMwf8Spg=
|
||||
github.com/fluxcd/pkg/ssh v0.6.0/go.mod h1:Puf+hWNzFsqdHtjDpsI3PTTvitZu41ObuPFblOdzrrI=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.8.0 h1:A6aLolxPV2Sll44SOHiX96lbXXmRZmS5BoEerkRHrfM=
|
||||
github.com/fluxcd/pkg/apis/kustomize v0.8.0/go.mod h1:9DPEVSfVIkiC2H3Dk6Ght4YJkswhYIaufXla4tB5Y84=
|
||||
github.com/fluxcd/pkg/apis/meta v0.19.0 h1:CX75e/eaRWZDTzNdMSWomY1InlssLKcS8GQDSg/aopI=
|
||||
github.com/fluxcd/pkg/apis/meta v0.19.0/go.mod h1:7b6prDPsViyAzoY7eRfSPS0/MbXpGGsOMvRq2QrTKa4=
|
||||
github.com/fluxcd/pkg/git v0.8.0 h1:7mIbdqSf+qXwY17+A+Kge2yWIJCMJ1p1DiBDGnKRohg=
|
||||
github.com/fluxcd/pkg/git v0.8.0/go.mod h1:3deiLPws4DSQ3hqwtQd7Dt66GXTN/4RcT/yHAljXaHo=
|
||||
github.com/fluxcd/pkg/git/gogit v0.5.0 h1:3Fzx2W16K/37ZHT6WmLFuRYgs+CGvzka+dwY7ktoxJE=
|
||||
github.com/fluxcd/pkg/git/gogit v0.5.0/go.mod h1:cqoJhKXCmWuN2ezD/2ECUYwR8gR7svMRJoHRr9VyTQc=
|
||||
github.com/fluxcd/pkg/gittestserver v0.8.0 h1:YrYe63KScKlLxx0GAiQthx2XqHDx0vKitIIx4JnDtIo=
|
||||
github.com/fluxcd/pkg/kustomize v0.13.0 h1:oC50lpGdz/04aH4dPS/kRBjo+7PUx7BgGsJtSS0CmmE=
|
||||
github.com/fluxcd/pkg/kustomize v0.13.0/go.mod h1:6vAmxEe/41jBEspGq4OZA/4WlnszPyavm74TGSEVpXg=
|
||||
github.com/fluxcd/pkg/oci v0.18.0 h1:x5n3gW1lX6wrqvWP4ZkOXJ8LqLKy891uKwifCXSqKi4=
|
||||
github.com/fluxcd/pkg/oci v0.18.0/go.mod h1:zXoxvE4uuIEOgA98IM5Wv/uRxs7sdbaTlGDjzHb9yiA=
|
||||
github.com/fluxcd/pkg/runtime v0.27.0 h1:zVA95Z0KvNjvZxEZhvIbJyJIwtaiv1aVttHZ4YB/FzY=
|
||||
github.com/fluxcd/pkg/runtime v0.27.0/go.mod h1:fC1l4Wv1hnsqPKB46eDZBXF8RMZm5FXeU4bnJkwGkqk=
|
||||
github.com/fluxcd/pkg/sourceignore v0.3.0 h1:pFO3hKV9ub+2SrNZPZE7xfiRhxsycRrd7JK7qB26nVw=
|
||||
github.com/fluxcd/pkg/sourceignore v0.3.0/go.mod h1:ak3Tve/KwVzytZ5V2yBlGGpTJ/2oQ9kcP3iuwBOAHGo=
|
||||
github.com/fluxcd/pkg/ssa v0.23.0 h1:e51n2642tyl8iytYQ68geg8E/6tLJcYqXl83HFrJcr4=
|
||||
github.com/fluxcd/pkg/ssa v0.23.0/go.mod h1:fbnulY5zeKBC6dXwNIgMc9DfPjEgjfhweL031/9ZFKQ=
|
||||
github.com/fluxcd/pkg/ssh v0.7.0 h1:FX5ky8SU9dYwbM6zEIDR3TSveLF01iyS95CtB5Ykpno=
|
||||
github.com/fluxcd/pkg/ssh v0.7.0/go.mod h1:tCVZJI8jPOL0XCInJOrYGKapWA/zZCzqPtpiYUSQxww=
|
||||
github.com/fluxcd/pkg/tar v0.2.0 h1:HEUHgONQYsJGeZZ4x6h5nQU9Aox1I4T3bOp1faWTqf8=
|
||||
github.com/fluxcd/pkg/tar v0.2.0/go.mod h1:w0/TOC7kwBJhnSJn7TCABkc/I7ib1f2Yz6vOsbLBnhw=
|
||||
github.com/fluxcd/pkg/untar v0.2.0 h1:sJXU+FbJcNUb2ffLJNjeR3hwt3X2loVpOMlCUjyFw6E=
|
||||
github.com/fluxcd/pkg/untar v0.2.0/go.mod h1:33AyoWaPpjX/xXpczcfhQh2AkB63TFwiR2YwROtv23E=
|
||||
github.com/fluxcd/pkg/version v0.2.0 h1:jG22c59Bsv6vL51N7Bqn8tjHArYOXrjbIkGArlIrv5w=
|
||||
github.com/fluxcd/pkg/version v0.2.0/go.mod h1:umN1VAOV0sB1JDVwb8eXZzuuqIAEku+y+vcCVBBUIf0=
|
||||
github.com/fluxcd/source-controller/api v0.31.0 h1:4PZQt2XILTUZ/2JOVGzAIpNDXjx8n10skAhuBHa9tVw=
|
||||
github.com/fluxcd/source-controller/api v0.31.0/go.mod h1:XOf8hJB7jFcAKiOb8HVZcegkBeNSb4g0nxqnNjeVufg=
|
||||
github.com/fluxcd/source-controller/api v0.34.0 h1:M2kD95IdpmHcDNy78K6T6p7niC38LGwSrKq8XAZEJY0=
|
||||
github.com/fluxcd/source-controller/api v0.34.0/go.mod h1:w3PDdR+FZyq3zyyUDxz6vY3CKByZfYAjkzJUxuUXCuc=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
|
||||
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
@@ -264,7 +270,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@@ -275,18 +280,15 @@ github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34
|
||||
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
|
||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
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=
|
||||
@@ -300,8 +302,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -317,10 +317,8 @@ 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.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
|
||||
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/gonvenience/bunt v1.3.4 h1:Row599Ohja2BPooaqd1tHYdTAKu6SWq7W/UeakTXddM=
|
||||
@@ -337,8 +335,8 @@ github.com/gonvenience/ytbx v1.4.4 h1:jQopwyaLsVGuwdxSiN4WkXjsEaFNPJ3V4lUj7eyEpz
|
||||
github.com/gonvenience/ytbx v1.4.4/go.mod h1:w37+MKCPcCMY/jpPNmEklD4xKqrOAVBO6kIWW2+uI6M=
|
||||
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 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=
|
||||
github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -349,16 +347,15 @@ 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.1/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.3/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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.12.0 h1:nidOEtFYlgPCRqxCKj/4c/js940HVWplCWc5ftdfdUA=
|
||||
github.com/google/go-containerregistry v0.12.0/go.mod h1:sdIK+oHQO7B93xI8UweYdl887YhuIwg9vz8BSLH3+8k=
|
||||
github.com/google/go-github/v47 v47.0.0 h1:eQap5bIRZibukP0VhngWgpuM0zhY4xntqOzn6DhdkE4=
|
||||
github.com/google/go-github/v47 v47.0.0/go.mod h1:DRjdvizXE876j0YOZwInB1ESpOcU/xFBClNiQLSdorE=
|
||||
github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k=
|
||||
github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo=
|
||||
github.com/google/go-github/v48 v48.2.0 h1:68puzySE6WqUY9KWmpOsDEQfDZsso98rT6pZcz9HqcE=
|
||||
github.com/google/go-github/v48 v48.2.0/go.mod h1:dDlehKBDo850ZPvCTK0sEqTCVWcrGl2LcDiajkYi89Y=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -366,8 +363,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
@@ -375,24 +370,14 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
@@ -401,17 +386,17 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
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.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
@@ -419,9 +404,9 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
|
||||
github.com/homeport/dyff v1.5.6 h1:6PNzGM0azeYXs401RZSLyIUS4sIX+YY3WBEZ3bnzkiE=
|
||||
github.com/homeport/dyff v1.5.6/go.mod h1:cMmplDz/DeUWPB4T/sD9GDpuTnMD2nk3rjn2f+5roEU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
@@ -445,8 +430,9 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
||||
@@ -470,7 +456,6 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
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.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
@@ -491,21 +476,21 @@ github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
|
||||
github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f h1:2+myh5ml7lgEU/51gbeLHfKGNfgEQQIWrlbdaOsidbQ=
|
||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
|
||||
github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c h1:RC8WMpjonrBfyAh6VN/POIPtYD5tRAq0qMqCRjQNK+g=
|
||||
github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c/go.mod h1:9OcmHNQQUTbk4XCffrLgN1NEKc2mh5u++biHVrvHsSU=
|
||||
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=
|
||||
@@ -515,7 +500,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||
github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@@ -525,18 +509,20 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo/v2 v2.3.0 h1:kUMoxMoQG3ogk/QWyKh3zibV7BKZ+xBpWil1cTylVqc=
|
||||
github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI=
|
||||
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||
github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow=
|
||||
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
|
||||
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
|
||||
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
|
||||
github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI=
|
||||
github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -551,13 +537,14 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
|
||||
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
|
||||
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
|
||||
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
@@ -577,8 +564,6 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
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/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@@ -593,24 +578,24 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
|
||||
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
|
||||
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U=
|
||||
github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8=
|
||||
github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRzJr4=
|
||||
@@ -620,10 +605,12 @@ github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlI
|
||||
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
|
||||
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo=
|
||||
github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c=
|
||||
github.com/xanzy/go-gitlab v0.73.1 h1:UMagqUZLJdjss1SovIC+kJCH4k2AZWXl58gJd38Y/hI=
|
||||
github.com/xanzy/go-gitlab v0.73.1/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA=
|
||||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
|
||||
github.com/xanzy/go-gitlab v0.77.0 h1:UrbGlxkWVCbkpa6Fk6cM8ARh+rLACWemkJnsawT7t98=
|
||||
github.com/xanzy/go-gitlab v0.77.0/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA=
|
||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
||||
github.com/xanzy/ssh-agent v0.3.2/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
@@ -633,7 +620,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/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=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
@@ -646,15 +632,13 @@ 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.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
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.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 h1:5/KzhcSqd4UgY51l17r7C5g/JiE6DRw1Vq7VJfQHuMc=
|
||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2/go.mod h1:kIVgS18CjmEC3PqMd5kaJSGEifyV/CeB9x506ZJ1Vbk=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
|
||||
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -665,9 +649,12 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -690,8 +677,6 @@ 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-20201208152925-83fdc39ff7b5/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=
|
||||
@@ -700,12 +685,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
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.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -735,42 +717,28 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
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-20201031054903-ff519b6c9102/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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
|
||||
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
|
||||
golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU=
|
||||
golang.org/x/oauth2 v0.2.0/go.mod h1:Cwn6afJ8jrQwYMxQDTpISoXmXW9I6qF6vDeuuoX3Ibs=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -781,7 +749,6 @@ 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/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -801,7 +768,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -822,54 +788,47 @@ 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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/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-20210423082822-04245dca01da/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-20210514084401-e8d321eab015/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-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
@@ -880,7 +839,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -911,20 +869,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/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.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
|
||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||
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=
|
||||
@@ -947,20 +895,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
||||
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
||||
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
||||
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
||||
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
||||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -999,34 +933,6 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
@@ -1040,20 +946,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
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=
|
||||
@@ -1094,7 +989,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@@ -1103,36 +997,35 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ=
|
||||
k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI=
|
||||
k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k=
|
||||
k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo=
|
||||
k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc=
|
||||
k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo=
|
||||
k8s.io/cli-runtime v0.25.3 h1:Zs7P7l7db/5J+KDePOVtDlArAa9pZXaDinGWGZl0aM8=
|
||||
k8s.io/cli-runtime v0.25.3/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4=
|
||||
k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0=
|
||||
k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA=
|
||||
k8s.io/component-base v0.25.3 h1:UrsxciGdrCY03ULT1h/S/gXFCOPnLhUVwSyx+hM/zq4=
|
||||
k8s.io/component-base v0.25.3/go.mod h1:WYoS8L+IlTZgU7rhAl5Ctpw0WdMxDfCC5dkxcEFa/TI=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
|
||||
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
|
||||
k8s.io/kubectl v0.25.3 h1:HnWJziEtmsm4JaJiKT33kG0kadx68MXxUE8UEbXnN4U=
|
||||
k8s.io/kubectl v0.25.3/go.mod h1:glU7PiVj/R6Ud4A9FJdTcJjyzOtCJyc0eO7Mrbh3jlI=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ=
|
||||
k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg=
|
||||
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
|
||||
k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM=
|
||||
k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ=
|
||||
k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
|
||||
k8s.io/cli-runtime v0.26.1 h1:f9+bRQ1V3elQsx37KmZy5fRAh56mVLbE9A7EMdlqVdI=
|
||||
k8s.io/cli-runtime v0.26.1/go.mod h1:+e5Ym/ARySKscUhZ8K3hZ+ZBo/wYPIcg+7b5sFYi6Gg=
|
||||
k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU=
|
||||
k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE=
|
||||
k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4=
|
||||
k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU=
|
||||
k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M=
|
||||
k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20221110221610-a28e98eb7c70 h1:zfqQc1V6/ZgGpvrOVvr62OjiqQX4lZjfznK34NQwkqw=
|
||||
k8s.io/kube-openapi v0.0.0-20221110221610-a28e98eb7c70/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
|
||||
k8s.io/kubectl v0.26.1 h1:K8A0Jjlwg8GqrxOXxAbjY5xtmXYeYjLU96cHp2WMQ7s=
|
||||
k8s.io/kubectl v0.26.1/go.mod h1:miYFVzldVbdIiXMrHZYmL/EDWwJKM+F0sSsdxsATFPo=
|
||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y=
|
||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/cli-utils v0.33.0 h1:/ioqfYu0hVeR2T2SDH3WVPgpqiJkrzqjJFrQ3u+baHk=
|
||||
sigs.k8s.io/cli-utils v0.33.0/go.mod h1:g/zB9hJ5eUN7zIEBIxrO0CwhXU4YISJ+BkLJzvWwlEs=
|
||||
sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ=
|
||||
sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI=
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/cli-utils v0.34.0 h1:zCUitt54f0/MYj/ajVFnG6XSXMhpZ72O/3RewIchW8w=
|
||||
sigs.k8s.io/cli-utils v0.34.0/go.mod h1:EXyMwPMu9OL+LRnj0JEMsGG/fRvbgFadcVlSnE8RhFs=
|
||||
sigs.k8s.io/controller-runtime v0.14.2 h1:P6IwDhbsRWsBClt/8/h8Zy36bCuGuW5Op7MHpFrN/60=
|
||||
sigs.k8s.io/controller-runtime v0.14.2/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM=
|
||||
sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s=
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk=
|
||||
|
||||
@@ -9,6 +9,9 @@ To install the latest release run:
|
||||
curl -s https://raw.githubusercontent.com/fluxcd/flux2/main/install/flux.sh | sudo bash
|
||||
```
|
||||
|
||||
**Note**: You may want to export the `GITHUB_TOKEN` environment variable using a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
|
||||
to avoid GitHub API rate-limiting errors if executing the install script repeatedly during a short time frame.
|
||||
|
||||
The install script does the following:
|
||||
* attempts to detect your OS
|
||||
* downloads and unpacks the release tar file in a temporary directory
|
||||
|
||||
@@ -112,10 +112,10 @@ download() {
|
||||
|
||||
case $DOWNLOADER in
|
||||
curl)
|
||||
curl -o "$1" -sfL "$2"
|
||||
curl -u user:$GITHUB_TOKEN -o "$1" -sfL "$2"
|
||||
;;
|
||||
wget)
|
||||
wget -qO "$1" "$2"
|
||||
wget --auth-no-challenge --user=user --password=$GITHUB_TOKEN -qO "$1" "$2"
|
||||
;;
|
||||
*)
|
||||
fatal "Incorrect executable '${DOWNLOADER}'"
|
||||
|
||||
@@ -42,8 +42,8 @@ import (
|
||||
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/kustomize"
|
||||
"github.com/fluxcd/pkg/kustomize/filesys"
|
||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
)
|
||||
@@ -76,10 +76,13 @@ type Builder struct {
|
||||
kustomization *kustomizev1.Kustomization
|
||||
timeout time.Duration
|
||||
spinner *yacspin.Spinner
|
||||
dryRun bool
|
||||
}
|
||||
|
||||
// BuilderOptionFunc is a function that configures a Builder
|
||||
type BuilderOptionFunc func(b *Builder) error
|
||||
|
||||
// WithKustomizationFile sets the kustomization file
|
||||
func WithKustomizationFile(file string) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.kustomizationFile = file
|
||||
@@ -87,6 +90,7 @@ func WithKustomizationFile(file string) BuilderOptionFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// WithTimeout sets the timeout for the builder
|
||||
func WithTimeout(timeout time.Duration) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.timeout = timeout
|
||||
@@ -116,24 +120,55 @@ func WithProgressBar() BuilderOptionFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// WithClientConfig sets the client configuration
|
||||
func WithClientConfig(rcg *genericclioptions.ConfigFlags, clientOpts *runclient.Options) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
kubeClient, err := utils.KubeClient(rcg, clientOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
restMapper, err := rcg.ToRESTMapper()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.client = kubeClient
|
||||
b.restMapper = restMapper
|
||||
b.namespace = *rcg.Namespace
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace sets the namespace
|
||||
func WithNamespace(namespace string) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.namespace = namespace
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDryRun sets the dry-run flag
|
||||
func WithDryRun(dryRun bool) BuilderOptionFunc {
|
||||
return func(b *Builder) error {
|
||||
b.dryRun = dryRun
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// NewBuilder returns a new Builder
|
||||
// to dp : create functional options
|
||||
func NewBuilder(rcg *genericclioptions.ConfigFlags, clientOpts *runclient.Options, name, resources string, opts ...BuilderOptionFunc) (*Builder, error) {
|
||||
kubeClient, err := utils.KubeClient(rcg, clientOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
restMapper, err := rcg.ToRESTMapper()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// It takes a kustomization name and a path to the resources
|
||||
// It also takes a list of BuilderOptionFunc to configure the builder
|
||||
// One of the options is WithClientConfig, that must be provided for the builder to work
|
||||
// with the k8s cluster
|
||||
// One other option is WithKustomizationFile, that must be provided for the builder to work
|
||||
// with a local kustomization file. If the kustomization file is not provided, the builder
|
||||
// will try to retrieve the kustomization object from the k8s cluster.
|
||||
// WithDryRun sets the dry-run flag, and needs to be provided if the builder is used for
|
||||
// a dry-run. This flag works in conjunction with WithKustomizationFile, because the
|
||||
// kustomization object is not retrieved from the k8s cluster when the dry-run flag is set.
|
||||
func NewBuilder(name, resources string, opts ...BuilderOptionFunc) (*Builder, error) {
|
||||
b := &Builder{
|
||||
client: kubeClient,
|
||||
restMapper: restMapper,
|
||||
name: name,
|
||||
namespace: *rcg.Namespace,
|
||||
resourcesPath: resources,
|
||||
}
|
||||
|
||||
@@ -147,6 +182,14 @@ func NewBuilder(rcg *genericclioptions.ConfigFlags, clientOpts *runclient.Option
|
||||
b.timeout = defaultTimeout
|
||||
}
|
||||
|
||||
if b.dryRun && b.kustomizationFile == "" {
|
||||
return nil, fmt.Errorf("kustomization file is required for dry-run")
|
||||
}
|
||||
|
||||
if !b.dryRun && b.client == nil {
|
||||
return nil, fmt.Errorf("client is required for live run")
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -188,7 +231,7 @@ func (b *Builder) build() (m resmap.ResMap, err error) {
|
||||
defer cancel()
|
||||
|
||||
// Get the kustomization object
|
||||
k := &kustomizev1.Kustomization{}
|
||||
var k *kustomizev1.Kustomization
|
||||
if b.kustomizationFile != "" {
|
||||
k, err = b.unMarshallKustomization()
|
||||
if err != nil {
|
||||
@@ -273,7 +316,7 @@ func (b *Builder) generate(kustomization kustomizev1.Kustomization, dirPath stri
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
gen := kustomize.NewGenerator(unstructured.Unstructured{Object: data})
|
||||
gen := kustomize.NewGenerator("", unstructured.Unstructured{Object: data})
|
||||
|
||||
// acuire the lock
|
||||
b.mu.Lock()
|
||||
@@ -283,17 +326,13 @@ func (b *Builder) generate(kustomization kustomizev1.Kustomization, dirPath stri
|
||||
}
|
||||
|
||||
func (b *Builder) do(ctx context.Context, kustomization kustomizev1.Kustomization, dirPath string) (resmap.ResMap, error) {
|
||||
// TODO(hidde): provide option to enforce FS boundaries of local build
|
||||
fs, err := filesys.MakeFsOnDiskSecureBuild("/")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("kustomization build failed: %w", err)
|
||||
}
|
||||
fs := filesys.MakeFsOnDisk()
|
||||
|
||||
// acuire the lock
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
m, err := kustomize.BuildKustomization(fs, dirPath)
|
||||
m, err := kustomize.Build(fs, dirPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("kustomize build failed: %w", err)
|
||||
}
|
||||
@@ -305,7 +344,7 @@ func (b *Builder) do(ctx context.Context, kustomization kustomizev1.Kustomizatio
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outRes, err := kustomize.SubstituteVariables(ctx, b.client, unstructured.Unstructured{Object: data}, res)
|
||||
outRes, err := kustomize.SubstituteVariables(ctx, b.client, unstructured.Unstructured{Object: data}, res, b.dryRun)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("var substitution failed for '%s': %w", res.GetName(), err)
|
||||
}
|
||||
|
||||
@@ -27,20 +27,22 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/printers"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
"github.com/gonvenience/bunt"
|
||||
"github.com/gonvenience/ytbx"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/homeport/dyff/pkg/dyff"
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
|
||||
"sigs.k8s.io/cli-utils/pkg/object"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/fluxcd/pkg/ssa"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/printers"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
func (b *Builder) Manager() (*ssa.ResourceManager, error) {
|
||||
@@ -85,7 +87,7 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var diffErrs error
|
||||
var diffErrs []error
|
||||
// create an inventory of objects to be reconciled
|
||||
newInventory := newInventory()
|
||||
for _, obj := range objects {
|
||||
@@ -97,7 +99,7 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
change, liveObject, mergedObject, err := resourceManager.Diff(ctx, obj, diffOptions)
|
||||
if err != nil {
|
||||
// gather errors and continue, as we want to see all the diffs
|
||||
diffErrs = multierror.Append(diffErrs, err)
|
||||
diffErrs = append(diffErrs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -135,7 +137,7 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
b.spinner.Message("processing inventory")
|
||||
}
|
||||
|
||||
if b.kustomization.Spec.Prune && diffErrs == nil {
|
||||
if b.kustomization.Spec.Prune && len(diffErrs) == 0 {
|
||||
oldStatus := b.kustomization.Status.DeepCopy()
|
||||
if oldStatus.Inventory != nil {
|
||||
diffObjects, err := diffInventory(oldStatus.Inventory, newInventory)
|
||||
@@ -155,7 +157,7 @@ func (b *Builder) Diff() (string, bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return output.String(), createdOrDrifted, diffErrs
|
||||
return output.String(), createdOrDrifted, errors.Reduce(errors.Flatten(errors.NewAggregate(diffErrs)))
|
||||
}
|
||||
|
||||
func writeYamls(liveObject, mergedObject *unstructured.Unstructured) (string, string, string, error) {
|
||||
|
||||
63
internal/utils/objectutil.go
Normal file
63
internal/utils/objectutil.go
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright 2023 The Flux authors
|
||||
Copyright 2018 The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// TODO: Remove this when
|
||||
// https://github.com/kubernetes-sigs/controller-runtime/blob/c783d2527a7da76332a2d8d563a6ca0b80c12122/pkg/client/apiutil/apimachinery.go#L76-L104
|
||||
// is included in a semver release.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||
)
|
||||
|
||||
// IsAPINamespaced returns true if the object is namespace scoped.
|
||||
// For unstructured objects the gvk is found from the object itself.
|
||||
func IsAPINamespaced(obj runtime.Object, scheme *runtime.Scheme, restmapper apimeta.RESTMapper) (bool, error) {
|
||||
gvk, err := apiutil.GVKForObject(obj, scheme)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return IsAPINamespacedWithGVK(gvk, scheme, restmapper)
|
||||
}
|
||||
|
||||
// IsAPINamespacedWithGVK returns true if the object having the provided
|
||||
// GVK is namespace scoped.
|
||||
func IsAPINamespacedWithGVK(gk schema.GroupVersionKind, scheme *runtime.Scheme, restmapper apimeta.RESTMapper) (bool, error) {
|
||||
restmapping, err := restmapper.RESTMapping(schema.GroupKind{Group: gk.Group, Kind: gk.Kind})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get restmapping: %w", err)
|
||||
}
|
||||
|
||||
scope := restmapping.Scope.Name()
|
||||
|
||||
if scope == "" {
|
||||
return false, errors.New("scope cannot be identified, empty scope returned")
|
||||
}
|
||||
|
||||
if scope != apimeta.RESTScopeNameRoot {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
@@ -45,7 +45,7 @@ import (
|
||||
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/v1beta2"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||
"github.com/fluxcd/pkg/version"
|
||||
@@ -54,9 +54,6 @@ import (
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
)
|
||||
|
||||
type Utils struct {
|
||||
}
|
||||
|
||||
type ExecMode string
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.26.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.26.0/helm-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.29.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.29.0/helm-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.26.1/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.26.1/image-automation-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.29.0/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.29.0/image-automation-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.22.1/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.22.1/image-reflector-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.24.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.24.0/image-reflector-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.30.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.30.0/kustomize-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.33.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.33.0/kustomize-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.28.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.28.0/notification-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.31.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.31.0/notification-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.31.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.31.0/source-controller.deployment.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.34.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.34.0/source-controller.deployment.yaml
|
||||
- account.yaml
|
||||
transformers:
|
||||
- labels.yaml
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.31.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.30.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.26.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.28.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.22.1/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.26.1/image-automation-controller.crds.yaml
|
||||
- https://github.com/fluxcd/source-controller/releases/download/v0.34.0/source-controller.crds.yaml
|
||||
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.33.0/kustomize-controller.crds.yaml
|
||||
- https://github.com/fluxcd/helm-controller/releases/download/v0.29.0/helm-controller.crds.yaml
|
||||
- https://github.com/fluxcd/notification-controller/releases/download/v0.31.0/notification-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.24.0/image-reflector-controller.crds.yaml
|
||||
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.29.0/image-automation-controller.crds.yaml
|
||||
|
||||
@@ -20,6 +20,8 @@ images:
|
||||
newName: ghcr.io/fluxcd/kustomize-controller
|
||||
- name: fluxcd/helm-controller
|
||||
newName: ghcr.io/fluxcd/helm-controller
|
||||
- name: fluxcd/notification-controller
|
||||
newName: ghcr.io/fluxcd/notification-controller
|
||||
- name: fluxcd/image-reflector-controller
|
||||
newName: ghcr.io/fluxcd/image-reflector-controller
|
||||
- name: fluxcd/image-automation-controller
|
||||
|
||||
@@ -6,7 +6,7 @@ spec:
|
||||
interval: 5m
|
||||
chart:
|
||||
spec:
|
||||
version: "35.x"
|
||||
version: "41.x"
|
||||
chart: kube-prometheus-stack
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
|
||||
@@ -4,4 +4,6 @@ metadata:
|
||||
name: prometheus-community
|
||||
spec:
|
||||
interval: 120m
|
||||
# OCI builds for kube-prometheus-stack have been temporarily disabled (see https://github.com/prometheus-community/helm-charts/issues/2940).
|
||||
type: default
|
||||
url: https://prometheus-community.github.io/helm-charts
|
||||
|
||||
@@ -19,12 +19,14 @@ package bootstrap
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
gogit "github.com/go-git/go-git/v5"
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
gogit "github.com/fluxcd/go-git/v5"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
@@ -39,35 +41,35 @@ import (
|
||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git"
|
||||
"github.com/fluxcd/flux2/pkg/log"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/install"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/kustomization"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/sourcesecret"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/sync"
|
||||
"github.com/fluxcd/flux2/pkg/status"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/repository"
|
||||
)
|
||||
|
||||
type PlainGitBootstrapper struct {
|
||||
url string
|
||||
branch string
|
||||
caBundle []byte
|
||||
url string
|
||||
branch string
|
||||
|
||||
author git.Author
|
||||
signature git.Signature
|
||||
commitMessageAppendix string
|
||||
|
||||
gpgKeyRingPath string
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
gpgKeyRing openpgp.EntityList
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
|
||||
restClientGetter genericclioptions.RESTClientGetter
|
||||
restClientOptions *runclient.Options
|
||||
|
||||
postGenerateSecret []PostGenerateSecretFunc
|
||||
|
||||
git git.Git
|
||||
kube client.Client
|
||||
logger log.Logger
|
||||
gitClient repository.Client
|
||||
kube client.Client
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
type GitOption interface {
|
||||
@@ -94,10 +96,10 @@ func (o postGenerateSecret) applyGit(b *PlainGitBootstrapper) {
|
||||
b.postGenerateSecret = append(b.postGenerateSecret, PostGenerateSecretFunc(o))
|
||||
}
|
||||
|
||||
func NewPlainGitProvider(git git.Git, kube client.Client, opts ...GitOption) (*PlainGitBootstrapper, error) {
|
||||
func NewPlainGitProvider(git repository.Client, kube client.Client, opts ...GitOption) (*PlainGitBootstrapper, error) {
|
||||
b := &PlainGitBootstrapper{
|
||||
git: git,
|
||||
kube: kube,
|
||||
gitClient: git,
|
||||
kube: kube,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt.applyGit(b)
|
||||
@@ -107,7 +109,7 @@ func NewPlainGitProvider(git git.Git, kube client.Client, opts ...GitOption) (*P
|
||||
|
||||
func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options, _ sourcesecret.Options) error {
|
||||
// Clone if not already
|
||||
if _, err := b.git.Status(); err != nil {
|
||||
if _, err := b.gitClient.Head(); err != nil {
|
||||
if err != git.ErrNoGitRepository {
|
||||
return err
|
||||
}
|
||||
@@ -115,7 +117,17 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
||||
b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
|
||||
var cloned bool
|
||||
if err = retry(1, 2*time.Second, func() (err error) {
|
||||
cloned, err = b.git.Clone(ctx, b.url, b.branch, b.caBundle)
|
||||
_, err = b.gitClient.Clone(ctx, b.url, repository.CloneOptions{
|
||||
CheckoutStrategy: repository.CheckoutStrategy{
|
||||
Branch: b.branch,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
b.logger.Warningf(" clone failure: %s", err)
|
||||
}
|
||||
if err == nil {
|
||||
cloned = true
|
||||
}
|
||||
return
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to clone repository: %w", err)
|
||||
@@ -133,28 +145,33 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
||||
}
|
||||
b.logger.Successf("generated component manifests")
|
||||
|
||||
// Write manifest to Git repository
|
||||
if err = b.git.Write(manifests.Path, strings.NewReader(manifests.Content)); err != nil {
|
||||
return fmt.Errorf("failed to write manifest %q: %w", manifests.Path, err)
|
||||
// Write generated files and make a commit
|
||||
var signer *openpgp.Entity
|
||||
if b.gpgKeyRing != nil {
|
||||
signer, err = getOpenPgpEntity(b.gpgKeyRing, b.gpgPassphrase, b.gpgKeyID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate OpenPGP entity: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
commit, err := b.git.Commit(git.Commit{
|
||||
Author: b.author,
|
||||
|
||||
commit, err := b.gitClient.Commit(git.Commit{
|
||||
Author: b.signature,
|
||||
Message: commitMsg,
|
||||
}, gpgOpts)
|
||||
}, repository.WithFiles(map[string]io.Reader{
|
||||
manifests.Path: strings.NewReader(manifests.Content),
|
||||
}), repository.WithSigner(signer))
|
||||
if err != nil && err != git.ErrNoStagedFiles {
|
||||
return fmt.Errorf("failed to commit sync manifests: %w", err)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
|
||||
b.logger.Actionf("pushing component manifests to %q", b.url)
|
||||
if err = b.git.Push(ctx, b.caBundle); err != nil {
|
||||
if err = b.gitClient.Push(ctx); err != nil {
|
||||
return fmt.Errorf("failed to push manifests: %w", err)
|
||||
}
|
||||
} else {
|
||||
@@ -165,16 +182,16 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
|
||||
if mustInstallManifests(ctx, b.kube, options.Namespace) {
|
||||
b.logger.Actionf("installing components in %q namespace", options.Namespace)
|
||||
|
||||
componentsYAML := filepath.Join(b.git.Path(), manifests.Path)
|
||||
componentsYAML := filepath.Join(b.gitClient.Path(), manifests.Path)
|
||||
kfile := filepath.Join(filepath.Dir(componentsYAML), konfig.DefaultKustomizationFileName())
|
||||
if _, err := os.Stat(kfile); err == nil {
|
||||
// Apply the components and their patches
|
||||
if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.git.Path(), kfile); err != nil {
|
||||
if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.gitClient.Path(), kfile); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Apply the CRDs and controllers
|
||||
if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.git.Path(), componentsYAML); err != nil {
|
||||
if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.gitClient.Path(), componentsYAML); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -195,7 +212,7 @@ func (b *PlainGitBootstrapper) ReconcileSourceSecret(ctx context.Context, option
|
||||
}
|
||||
|
||||
// Return early if exists and no custom config is passed
|
||||
if ok && len(options.CAFilePath+options.PrivateKeyPath+options.Username+options.Password) == 0 {
|
||||
if ok && options.Keypair == nil && len(options.CAFile) == 0 && len(options.Username+options.Password) == 0 {
|
||||
b.logger.Successf("source secret up to date")
|
||||
return nil
|
||||
}
|
||||
@@ -236,12 +253,19 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
||||
}
|
||||
|
||||
// Clone if not already
|
||||
if _, err := b.git.Status(); err != nil {
|
||||
if _, err := b.gitClient.Head(); err != nil {
|
||||
if err == git.ErrNoGitRepository {
|
||||
b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
|
||||
var cloned bool
|
||||
if err = retry(1, 2*time.Second, func() (err error) {
|
||||
cloned, err = b.git.Clone(ctx, b.url, b.branch, b.caBundle)
|
||||
_, err = b.gitClient.Clone(ctx, b.url, repository.CloneOptions{
|
||||
CheckoutStrategy: repository.CheckoutStrategy{
|
||||
Branch: b.branch,
|
||||
},
|
||||
})
|
||||
if err == nil {
|
||||
cloned = true
|
||||
}
|
||||
return
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to clone repository: %w", err)
|
||||
@@ -259,41 +283,47 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
||||
if err != nil {
|
||||
return fmt.Errorf("sync manifests generation failed: %w", err)
|
||||
}
|
||||
if err = b.git.Write(manifests.Path, strings.NewReader(manifests.Content)); err != nil {
|
||||
return fmt.Errorf("failed to write manifest %q: %w", manifests.Path, err)
|
||||
}
|
||||
|
||||
// Create secure Kustomize FS
|
||||
fs, err := filesys.MakeFsOnDiskSecureBuild(b.git.Path())
|
||||
fs, err := filesys.MakeFsOnDiskSecureBuild(b.gitClient.Path())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize Kustomize file system: %w", err)
|
||||
}
|
||||
|
||||
if err = fs.WriteFile(filepath.Join(b.gitClient.Path(), manifests.Path), []byte(manifests.Content)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate Kustomization
|
||||
kusManifests, err := kustomization.Generate(kustomization.Options{
|
||||
FileSystem: fs,
|
||||
BaseDir: b.git.Path(),
|
||||
BaseDir: b.gitClient.Path(),
|
||||
TargetPath: filepath.Dir(manifests.Path),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s generation failed: %w", konfig.DefaultKustomizationFileName(), err)
|
||||
}
|
||||
if err = b.git.Write(kusManifests.Path, strings.NewReader(kusManifests.Content)); err != nil {
|
||||
return fmt.Errorf("failed to write manifest %q: %w", kusManifests.Path, err)
|
||||
}
|
||||
b.logger.Successf("generated sync manifests")
|
||||
|
||||
// Git commit generated
|
||||
gpgOpts := git.WithGpgSigningOption(b.gpgKeyRingPath, b.gpgPassphrase, b.gpgKeyID)
|
||||
// Write generated files and make a commit
|
||||
var signer *openpgp.Entity
|
||||
if b.gpgKeyRing != nil {
|
||||
signer, err = getOpenPgpEntity(b.gpgKeyRing, b.gpgPassphrase, b.gpgKeyID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate OpenPGP entity: %w", err)
|
||||
}
|
||||
}
|
||||
commitMsg := fmt.Sprintf("Add Flux sync manifests")
|
||||
if b.commitMessageAppendix != "" {
|
||||
commitMsg = commitMsg + "\n\n" + b.commitMessageAppendix
|
||||
}
|
||||
commit, err := b.git.Commit(git.Commit{
|
||||
Author: b.author,
|
||||
Message: commitMsg,
|
||||
}, gpgOpts)
|
||||
|
||||
commit, err := b.gitClient.Commit(git.Commit{
|
||||
Author: b.signature,
|
||||
Message: commitMsg,
|
||||
}, repository.WithFiles(map[string]io.Reader{
|
||||
kusManifests.Path: strings.NewReader(kusManifests.Content),
|
||||
}), repository.WithSigner(signer))
|
||||
if err != nil && err != git.ErrNoStagedFiles {
|
||||
return fmt.Errorf("failed to commit sync manifests: %w", err)
|
||||
}
|
||||
@@ -301,18 +331,22 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
||||
if err == nil {
|
||||
b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
|
||||
b.logger.Actionf("pushing sync manifests to %q", b.url)
|
||||
err = b.git.Push(ctx, b.caBundle)
|
||||
err = b.gitClient.Push(ctx)
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), gogit.ErrNonFastForwardUpdate.Error()) {
|
||||
b.logger.Waitingf("git conflict detected, retrying with a fresh clone")
|
||||
if err := os.RemoveAll(b.git.Path()); err != nil {
|
||||
if err := os.RemoveAll(b.gitClient.Path()); err != nil {
|
||||
return fmt.Errorf("failed to remove tmp dir: %w", err)
|
||||
}
|
||||
if err := os.Mkdir(b.git.Path(), 0o700); err != nil {
|
||||
if err := os.Mkdir(b.gitClient.Path(), 0o700); err != nil {
|
||||
return fmt.Errorf("failed to recreate tmp dir: %w", err)
|
||||
}
|
||||
if err = retry(1, 2*time.Second, func() (err error) {
|
||||
_, err = b.git.Clone(ctx, b.url, b.branch, b.caBundle)
|
||||
_, err = b.gitClient.Clone(ctx, b.url, repository.CloneOptions{
|
||||
CheckoutStrategy: repository.CheckoutStrategy{
|
||||
Branch: b.branch,
|
||||
},
|
||||
})
|
||||
return
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to clone repository: %w", err)
|
||||
@@ -327,7 +361,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
||||
|
||||
// Apply to cluster
|
||||
b.logger.Actionf("applying sync manifests")
|
||||
if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.git.Path(), filepath.Join(b.git.Path(), kusManifests.Path)); err != nil {
|
||||
if _, err := utils.Apply(ctx, b.restClientGetter, b.restClientOptions, b.gitClient.Path(), filepath.Join(b.gitClient.Path(), kusManifests.Path)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -337,7 +371,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
|
||||
}
|
||||
|
||||
func (b *PlainGitBootstrapper) ReportKustomizationHealth(ctx context.Context, options sync.Options, pollInterval, timeout time.Duration) error {
|
||||
head, err := b.git.Head()
|
||||
head, err := b.gitClient.Head()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -389,3 +423,42 @@ func (b *PlainGitBootstrapper) ReportComponentsHealth(ctx context.Context, insta
|
||||
b.logger.Successf("all components are healthy")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getOpenPgpEntity(keyRing openpgp.EntityList, passphrase, keyID string) (*openpgp.Entity, error) {
|
||||
if len(keyRing) == 0 {
|
||||
return nil, fmt.Errorf("empty GPG key ring")
|
||||
}
|
||||
|
||||
var entity *openpgp.Entity
|
||||
if keyID != "" {
|
||||
if strings.HasPrefix(keyID, "0x") {
|
||||
keyID = strings.TrimPrefix(keyID, "0x")
|
||||
}
|
||||
if len(keyID) != 16 {
|
||||
return nil, fmt.Errorf("invalid GPG key id length; expected %d, got %d", 16, len(keyID))
|
||||
}
|
||||
keyID = strings.ToUpper(keyID)
|
||||
|
||||
for _, ent := range keyRing {
|
||||
if ent.PrimaryKey.KeyIdString() == keyID {
|
||||
entity = ent
|
||||
}
|
||||
}
|
||||
|
||||
if entity == nil {
|
||||
return nil, fmt.Errorf("no GPG keyring matching key id '%s' found", keyID)
|
||||
}
|
||||
if entity.PrivateKey == nil {
|
||||
return nil, fmt.Errorf("keyring does not contain private key for key id '%s'", keyID)
|
||||
}
|
||||
} else {
|
||||
entity = keyRing[0]
|
||||
}
|
||||
|
||||
err := entity.PrivateKey.Decrypt([]byte(passphrase))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decrypt GPG private key: %w", err)
|
||||
}
|
||||
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ import (
|
||||
|
||||
"github.com/fluxcd/go-git-providers/gitprovider"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git"
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/provider"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/sourcesecret"
|
||||
"github.com/fluxcd/flux2/pkg/manifestgen/sync"
|
||||
"github.com/fluxcd/pkg/git/repository"
|
||||
)
|
||||
|
||||
type GitProviderBootstrapper struct {
|
||||
@@ -62,11 +62,12 @@ type GitProviderBootstrapper struct {
|
||||
provider gitprovider.Client
|
||||
}
|
||||
|
||||
func NewGitProviderBootstrapper(git git.Git, provider gitprovider.Client, kube client.Client, opts ...GitProviderOption) (*GitProviderBootstrapper, error) {
|
||||
func NewGitProviderBootstrapper(git repository.Client, provider gitprovider.Client,
|
||||
kube client.Client, opts ...GitProviderOption) (*GitProviderBootstrapper, error) {
|
||||
b := &GitProviderBootstrapper{
|
||||
PlainGitBootstrapper: &PlainGitBootstrapper{
|
||||
git: git,
|
||||
kube: kube,
|
||||
gitClient: git,
|
||||
kube: kube,
|
||||
},
|
||||
bootstrapTransportType: "https",
|
||||
syncTransportType: "ssh",
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
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,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
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 git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoGitRepository = errors.New("no git repository")
|
||||
ErrNoStagedFiles = errors.New("no staged files")
|
||||
)
|
||||
|
||||
type Author struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
|
||||
type Commit struct {
|
||||
Author
|
||||
Hash string
|
||||
Message string
|
||||
}
|
||||
|
||||
// Git is an interface for basic Git operations on a single branch of a
|
||||
// remote repository.
|
||||
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, options ...Option) (string, error)
|
||||
Push(ctx context.Context, caBundle []byte) error
|
||||
Status() (bool, error)
|
||||
Head() (string, error)
|
||||
Path() string
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
/*
|
||||
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 gogit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"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"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git"
|
||||
)
|
||||
|
||||
type GoGit struct {
|
||||
path string
|
||||
auth transport.AuthMethod
|
||||
repository *gogit.Repository
|
||||
}
|
||||
|
||||
type CommitOptions struct {
|
||||
GpgKeyPath string
|
||||
GpgKeyPassphrase string
|
||||
KeyID string
|
||||
}
|
||||
|
||||
func New(path string, auth transport.AuthMethod) *GoGit {
|
||||
return &GoGit{
|
||||
path: path,
|
||||
auth: auth,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GoGit) Init(url, branch string) (bool, error) {
|
||||
if g.repository != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
r, err := gogit.PlainInit(g.path, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if _, err = r.CreateRemote(&config.RemoteConfig{
|
||||
Name: gogit.DefaultRemoteName,
|
||||
URLs: []string{url},
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
branchRef := plumbing.NewBranchReferenceName(branch)
|
||||
if err = r.CreateBranch(&config.Branch{
|
||||
Name: branch,
|
||||
Remote: gogit.DefaultRemoteName,
|
||||
Merge: branchRef,
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
// PlainInit assumes the initial branch to always be master, we can
|
||||
// overwrite this by setting the reference of the Storer to a new
|
||||
// symbolic reference (as there are no commits yet) that points
|
||||
// the HEAD to our new branch.
|
||||
if err = r.Storer.SetReference(plumbing.NewSymbolicReference(plumbing.HEAD, branchRef)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
g.repository = r
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (g *GoGit) Clone(ctx context.Context, url, branch string, caBundle []byte) (bool, error) {
|
||||
branchRef := plumbing.NewBranchReferenceName(branch)
|
||||
r, err := gogit.PlainCloneContext(ctx, g.path, false, &gogit.CloneOptions{
|
||||
URL: url,
|
||||
Auth: g.auth,
|
||||
RemoteName: gogit.DefaultRemoteName,
|
||||
ReferenceName: branchRef,
|
||||
SingleBranch: true,
|
||||
|
||||
NoCheckout: false,
|
||||
Progress: nil,
|
||||
Tags: gogit.NoTags,
|
||||
CABundle: caBundle,
|
||||
})
|
||||
if err != nil {
|
||||
if err == transport.ErrEmptyRemoteRepository || isRemoteBranchNotFoundErr(err, branchRef.String()) {
|
||||
return g.Init(url, branch)
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
g.repository = r
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (g *GoGit) Write(path string, reader io.Reader) error {
|
||||
if g.repository == nil {
|
||||
return git.ErrNoGitRepository
|
||||
}
|
||||
|
||||
wt, err := g.repository.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := wt.Filesystem.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = io.Copy(f, reader)
|
||||
return err
|
||||
}
|
||||
|
||||
func (g *GoGit) Commit(message git.Commit, opts ...git.Option) (string, error) {
|
||||
if g.repository == nil {
|
||||
return "", git.ErrNoGitRepository
|
||||
}
|
||||
|
||||
wt, err := g.repository.Worktree()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
status, err := wt.Status()
|
||||
if err != nil {
|
||||
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
|
||||
// change to a broken symlink: so, detect and skip those.
|
||||
var changed bool
|
||||
for file, _ := range status {
|
||||
abspath := filepath.Join(g.path, file)
|
||||
info, err := os.Lstat(abspath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("checking if %s is a symlink: %w", file, err)
|
||||
}
|
||||
if info.Mode()&os.ModeSymlink > 0 {
|
||||
// symlinks are OK; broken symlinks are probably a result
|
||||
// of the bug mentioned above, but not of interest in any
|
||||
// case.
|
||||
if _, err := os.Stat(abspath); os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
_, _ = wt.Add(file)
|
||||
changed = true
|
||||
}
|
||||
|
||||
if !changed {
|
||||
head, err := g.repository.Head()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return head.Hash().String(), git.ErrNoStagedFiles
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
return commit.String(), nil
|
||||
}
|
||||
|
||||
func (g *GoGit) Push(ctx context.Context, caBundle []byte) error {
|
||||
if g.repository == nil {
|
||||
return git.ErrNoGitRepository
|
||||
}
|
||||
|
||||
return g.repository.PushContext(ctx, &gogit.PushOptions{
|
||||
RemoteName: gogit.DefaultRemoteName,
|
||||
Auth: g.auth,
|
||||
Progress: nil,
|
||||
CABundle: caBundle,
|
||||
})
|
||||
}
|
||||
|
||||
func (g *GoGit) Status() (bool, error) {
|
||||
if g.repository == nil {
|
||||
return false, git.ErrNoGitRepository
|
||||
}
|
||||
wt, err := g.repository.Worktree()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
status, err := wt.Status()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return status.IsClean(), nil
|
||||
}
|
||||
|
||||
func (g *GoGit) Head() (string, error) {
|
||||
if g.repository == nil {
|
||||
return "", git.ErrNoGitRepository
|
||||
}
|
||||
head, err := g.repository.Head()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return head.Hash().String(), nil
|
||||
}
|
||||
|
||||
func (g *GoGit) Path() string {
|
||||
return g.path
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
//go:build unit
|
||||
// +build unit
|
||||
|
||||
package gogit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/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
pkg/bootstrap/git/gogit/testdata/private.key
vendored
BIN
pkg/bootstrap/git/gogit/testdata/private.key
vendored
Binary file not shown.
@@ -17,11 +17,15 @@ limitations under the License.
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/bootstrap/git"
|
||||
"github.com/fluxcd/flux2/pkg/log"
|
||||
)
|
||||
|
||||
@@ -44,42 +48,28 @@ func (o branchOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
o.applyGit(b.PlainGitBootstrapper)
|
||||
}
|
||||
|
||||
func WithAuthor(name, email string) Option {
|
||||
return authorOption{
|
||||
func WithSignature(name, email string) Option {
|
||||
return signatureOption{
|
||||
Name: name,
|
||||
Email: email,
|
||||
}
|
||||
}
|
||||
|
||||
type authorOption git.Author
|
||||
type signatureOption git.Signature
|
||||
|
||||
func (o authorOption) applyGit(b *PlainGitBootstrapper) {
|
||||
func (o signatureOption) applyGit(b *PlainGitBootstrapper) {
|
||||
if o.Name != "" {
|
||||
b.author.Name = o.Name
|
||||
b.signature.Name = o.Name
|
||||
}
|
||||
if o.Email != "" {
|
||||
b.author.Email = o.Email
|
||||
b.signature.Email = o.Email
|
||||
}
|
||||
}
|
||||
|
||||
func (o authorOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
func (o signatureOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
o.applyGit(b.PlainGitBootstrapper)
|
||||
}
|
||||
|
||||
func WithCABundle(b []byte) Option {
|
||||
return caBundleOption(b)
|
||||
}
|
||||
|
||||
type caBundleOption []byte
|
||||
|
||||
func (o caBundleOption) applyGit(b *PlainGitBootstrapper) {
|
||||
b.caBundle = o
|
||||
}
|
||||
|
||||
func (o caBundleOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
b.caBundle = o
|
||||
}
|
||||
|
||||
func WithCommitMessageAppendix(appendix string) Option {
|
||||
return commitMessageAppendixOption(appendix)
|
||||
}
|
||||
@@ -131,22 +121,22 @@ func (o loggerOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
b.logger = o.logger
|
||||
}
|
||||
|
||||
func WithGitCommitSigning(path, passphrase, keyID string) Option {
|
||||
func WithGitCommitSigning(gpgKeyRing openpgp.EntityList, passphrase, keyID string) Option {
|
||||
return gitCommitSigningOption{
|
||||
gpgKeyRingPath: path,
|
||||
gpgPassphrase: passphrase,
|
||||
gpgKeyID: keyID,
|
||||
gpgKeyRing: gpgKeyRing,
|
||||
gpgPassphrase: passphrase,
|
||||
gpgKeyID: keyID,
|
||||
}
|
||||
}
|
||||
|
||||
type gitCommitSigningOption struct {
|
||||
gpgKeyRingPath string
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
gpgKeyRing openpgp.EntityList
|
||||
gpgPassphrase string
|
||||
gpgKeyID string
|
||||
}
|
||||
|
||||
func (o gitCommitSigningOption) applyGit(b *PlainGitBootstrapper) {
|
||||
b.gpgKeyRingPath = o.gpgKeyRingPath
|
||||
b.gpgKeyRing = o.gpgKeyRing
|
||||
b.gpgPassphrase = o.gpgPassphrase
|
||||
b.gpgKeyID = o.gpgKeyID
|
||||
}
|
||||
@@ -154,3 +144,18 @@ func (o gitCommitSigningOption) applyGit(b *PlainGitBootstrapper) {
|
||||
func (o gitCommitSigningOption) applyGitProvider(b *GitProviderBootstrapper) {
|
||||
o.applyGit(b.PlainGitBootstrapper)
|
||||
}
|
||||
|
||||
func LoadEntityListFromPath(path string) (openpgp.EntityList, error) {
|
||||
if path == "" {
|
||||
return nil, nil
|
||||
}
|
||||
r, err := os.Open(path)
|
||||
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, fmt.Errorf("unable to read GPG key ring: %w", err)
|
||||
}
|
||||
return entityList, nil
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package sourcesecret
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
|
||||
"github.com/fluxcd/pkg/ssh"
|
||||
)
|
||||
|
||||
type PrivateKeyAlgorithm string
|
||||
@@ -48,12 +50,12 @@ type Options struct {
|
||||
PrivateKeyAlgorithm PrivateKeyAlgorithm
|
||||
RSAKeyBits int
|
||||
ECDSACurve elliptic.Curve
|
||||
PrivateKeyPath string
|
||||
Keypair *ssh.KeyPair
|
||||
Username string
|
||||
Password string
|
||||
CAFilePath string
|
||||
CertFilePath string
|
||||
KeyFilePath string
|
||||
CAFile []byte
|
||||
CertFile []byte
|
||||
KeyFile []byte
|
||||
TargetPath string
|
||||
ManifestFile string
|
||||
}
|
||||
@@ -64,12 +66,11 @@ func MakeDefaultOptions() Options {
|
||||
Namespace: "flux-system",
|
||||
Labels: map[string]string{},
|
||||
PrivateKeyAlgorithm: RSAPrivateKeyAlgorithm,
|
||||
PrivateKeyPath: "",
|
||||
Username: "",
|
||||
Password: "",
|
||||
CAFilePath: "",
|
||||
CertFilePath: "",
|
||||
KeyFilePath: "",
|
||||
CAFile: []byte{},
|
||||
CertFile: []byte{},
|
||||
KeyFile: []byte{},
|
||||
ManifestFile: "secret.yaml",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,8 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
switch {
|
||||
case options.Username != "" && options.Password != "":
|
||||
// noop
|
||||
case len(options.PrivateKeyPath) > 0:
|
||||
if keypair, err = loadKeyPair(options.PrivateKeyPath, options.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case options.Keypair != nil:
|
||||
keypair = options.Keypair
|
||||
case len(options.PrivateKeyAlgorithm) > 0:
|
||||
if keypair, err = generateKeyPair(options); err != nil {
|
||||
return nil, err
|
||||
@@ -78,28 +76,11 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
|
||||
var hostKey []byte
|
||||
if keypair != nil {
|
||||
if hostKey, err = scanHostKey(options.SSHHostname); err != nil {
|
||||
if hostKey, err = ScanHostKey(options.SSHHostname); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var caFile []byte
|
||||
if options.CAFilePath != "" {
|
||||
if caFile, err = os.ReadFile(options.CAFilePath); err != nil {
|
||||
return nil, fmt.Errorf("failed to read CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var certFile, keyFile []byte
|
||||
if options.CertFilePath != "" && options.KeyFilePath != "" {
|
||||
if certFile, err = os.ReadFile(options.CertFilePath); err != nil {
|
||||
return nil, fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if keyFile, err = os.ReadFile(options.KeyFilePath); err != nil {
|
||||
return nil, fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var dockerCfgJson []byte
|
||||
if options.Registry != "" {
|
||||
dockerCfgJson, err = generateDockerConfigJson(options.Registry, options.Username, options.Password)
|
||||
@@ -108,7 +89,7 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
}
|
||||
}
|
||||
|
||||
secret := buildSecret(keypair, hostKey, caFile, certFile, keyFile, dockerCfgJson, options)
|
||||
secret := buildSecret(keypair, hostKey, options.CAFile, options.CertFile, options.KeyFile, dockerCfgJson, options)
|
||||
b, err := yaml.Marshal(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -120,6 +101,35 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func LoadKeyPairFromPath(path, password string) (*ssh.KeyPair, error) {
|
||||
if path == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open private key file: %w", err)
|
||||
}
|
||||
return LoadKeyPair(b, password)
|
||||
}
|
||||
|
||||
func LoadKeyPair(privateKey []byte, password string) (*ssh.KeyPair, error) {
|
||||
var ppk cryptssh.Signer
|
||||
var err error
|
||||
if password != "" {
|
||||
ppk, err = cryptssh.ParsePrivateKeyWithPassphrase(privateKey, []byte(password))
|
||||
} else {
|
||||
ppk, err = cryptssh.ParsePrivateKey(privateKey)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ssh.KeyPair{
|
||||
PublicKey: cryptssh.MarshalAuthorizedKey(ppk.PublicKey()),
|
||||
PrivateKey: privateKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, dockerCfg []byte, options Options) (secret corev1.Secret) {
|
||||
secret.TypeMeta = metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
@@ -143,16 +153,16 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, docke
|
||||
secret.StringData[PasswordSecretKey] = options.Password
|
||||
}
|
||||
|
||||
if caFile != nil {
|
||||
if len(caFile) != 0 {
|
||||
secret.StringData[CAFileSecretKey] = string(caFile)
|
||||
}
|
||||
|
||||
if certFile != nil && keyFile != nil {
|
||||
if len(certFile) != 0 && len(keyFile) != 0 {
|
||||
secret.StringData[CertFileSecretKey] = string(certFile)
|
||||
secret.StringData[KeyFileSecretKey] = string(keyFile)
|
||||
}
|
||||
|
||||
if keypair != nil && hostKey != nil {
|
||||
if keypair != nil && len(hostKey) != 0 {
|
||||
secret.StringData[PrivateKeySecretKey] = string(keypair.PrivateKey)
|
||||
secret.StringData[PublicKeySecretKey] = string(keypair.PublicKey)
|
||||
secret.StringData[KnownHostsSecretKey] = string(hostKey)
|
||||
@@ -165,29 +175,6 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, docke
|
||||
return
|
||||
}
|
||||
|
||||
func loadKeyPair(path string, password string) (*ssh.KeyPair, error) {
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open private key file: %w", err)
|
||||
}
|
||||
|
||||
var ppk cryptssh.Signer
|
||||
if password != "" {
|
||||
ppk, err = cryptssh.ParsePrivateKeyWithPassphrase(b, []byte(password))
|
||||
} else {
|
||||
ppk, err = cryptssh.ParsePrivateKey(b)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ssh.KeyPair{
|
||||
PublicKey: cryptssh.MarshalAuthorizedKey(ppk.PublicKey()),
|
||||
PrivateKey: b,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func generateKeyPair(options Options) (*ssh.KeyPair, error) {
|
||||
var keyGen ssh.KeyPairGenerator
|
||||
switch options.PrivateKeyAlgorithm {
|
||||
@@ -207,7 +194,7 @@ func generateKeyPair(options Options) (*ssh.KeyPair, error) {
|
||||
return pair, nil
|
||||
}
|
||||
|
||||
func scanHostKey(host string) ([]byte, error) {
|
||||
func ScanHostKey(host string) ([]byte, error) {
|
||||
if _, _, err := net.SplitHostPort(host); err != nil {
|
||||
// Assume we are dealing with a hostname without a port,
|
||||
// append the default SSH port as this is required for
|
||||
|
||||
@@ -48,7 +48,7 @@ func Test_passwordLoadKeyPair(t *testing.T) {
|
||||
pk, _ := os.ReadFile(tt.privateKeyPath)
|
||||
ppk, _ := os.ReadFile(tt.publicKeyPath)
|
||||
|
||||
got, err := loadKeyPair(tt.privateKeyPath, tt.password)
|
||||
got, err := LoadKeyPair(pk, tt.password)
|
||||
if err != nil {
|
||||
t.Errorf("loadKeyPair() error = %v", err)
|
||||
return
|
||||
@@ -67,24 +67,13 @@ func Test_passwordLoadKeyPair(t *testing.T) {
|
||||
func Test_PasswordlessLoadKeyPair(t *testing.T) {
|
||||
for algo, privateKey := range testdata.PEMBytes {
|
||||
t.Run(algo, func(t *testing.T) {
|
||||
f, err := os.CreateTemp("", "test-private-key-")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create temporary file. err: %s", err)
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
|
||||
if _, err = f.Write(privateKey); err != nil {
|
||||
t.Fatalf("unable to write private key to file. err: %s", err)
|
||||
}
|
||||
|
||||
got, err := loadKeyPair(f.Name(), "")
|
||||
got, err := LoadKeyPair(privateKey, "")
|
||||
if err != nil {
|
||||
t.Errorf("loadKeyPair() error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
pk, _ := os.ReadFile(f.Name())
|
||||
if !reflect.DeepEqual(got.PrivateKey, pk) {
|
||||
if !reflect.DeepEqual(got.PrivateKey, privateKey) {
|
||||
t.Errorf("PrivateKey %s != %s", got.PrivateKey, string(privateKey))
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/fluxcd/flux2/pkg/log"
|
||||
@@ -33,12 +34,13 @@ import (
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
|
||||
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta2"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
// Components removes all Kubernetes components that are part of Flux excluding the CRDs and namespace.
|
||||
func Components(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) {
|
||||
func Components(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error {
|
||||
var aggregateErr []error
|
||||
opts, dryRunStr := getDeleteOptions(dryRun)
|
||||
selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue}
|
||||
{
|
||||
@@ -47,6 +49,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
for _, r := range list.Items {
|
||||
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("Deployment/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("Deployment/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -59,6 +62,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
for _, r := range list.Items {
|
||||
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("Service/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("Service/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -71,6 +75,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
for _, r := range list.Items {
|
||||
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("NetworkPolicy/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("NetworkPolicy/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -83,6 +88,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
for _, r := range list.Items {
|
||||
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("ServiceAccount/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("ServiceAccount/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -95,6 +101,7 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
for _, r := range list.Items {
|
||||
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("ClusterRole/%s deletion failed: %s", r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("ClusterRole/%s deleted %s", r.Name, dryRunStr)
|
||||
}
|
||||
@@ -107,16 +114,20 @@ func Components(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
for _, r := range list.Items {
|
||||
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("ClusterRoleBinding/%s deletion failed: %s", r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("ClusterRoleBinding/%s deleted %s", r.Name, dryRunStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr)))
|
||||
}
|
||||
|
||||
// Finalizers removes all finalizes on Kubernetes components that have been added by a Flux controller.
|
||||
func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) {
|
||||
func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error {
|
||||
var aggregateErr []error
|
||||
opts, dryRunStr := getUpdateOptions(dryRun)
|
||||
{
|
||||
var list sourcev1.GitRepositoryList
|
||||
@@ -125,6 +136,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -138,6 +150,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -151,6 +164,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -164,6 +178,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -177,6 +192,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -190,6 +206,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -203,6 +220,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -216,6 +234,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -229,6 +248,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -242,6 +262,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -255,6 +276,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -268,6 +290,7 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
@@ -281,16 +304,19 @@ func Finalizers(ctx context.Context, logger log.Logger, kubeClient client.Client
|
||||
r.Finalizers = []string{}
|
||||
if err := kubeClient.Update(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr)))
|
||||
}
|
||||
|
||||
// CustomResourceDefinitions removes all Kubernetes CRDs that are a part of Flux.
|
||||
func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) {
|
||||
func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClient client.Client, dryRun bool) error {
|
||||
var aggregateErr []error
|
||||
opts, dryRunStr := getDeleteOptions(dryRun)
|
||||
selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue}
|
||||
{
|
||||
@@ -299,23 +325,28 @@ func CustomResourceDefinitions(ctx context.Context, logger log.Logger, kubeClien
|
||||
for _, r := range list.Items {
|
||||
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
|
||||
logger.Failuref("CustomResourceDefinition/%s deletion failed: %s", r.Name, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("CustomResourceDefinition/%s deleted %s", r.Name, dryRunStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr)))
|
||||
}
|
||||
|
||||
// Namespace removes the namespace Flux is installed in.
|
||||
func Namespace(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) {
|
||||
func Namespace(ctx context.Context, logger log.Logger, kubeClient client.Client, namespace string, dryRun bool) error {
|
||||
var aggregateErr []error
|
||||
opts, dryRunStr := getDeleteOptions(dryRun)
|
||||
ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
|
||||
if err := kubeClient.Delete(ctx, &ns, opts); err != nil {
|
||||
logger.Failuref("Namespace/%s deletion failed: %s", namespace, err.Error())
|
||||
aggregateErr = append(aggregateErr, err)
|
||||
} else {
|
||||
logger.Successf("Namespace/%s deleted %s", namespace, dryRunStr)
|
||||
}
|
||||
return errors.Reduce(errors.Flatten(errors.NewAggregate(aggregateErr)))
|
||||
}
|
||||
|
||||
func getDeleteOptions(dryRun bool) (*client.DeleteOptions, string) {
|
||||
|
||||
@@ -109,8 +109,8 @@ fields that are not restricted to the namespace of the containing object, listed
|
||||
| | `.spec.targetNamespace` | This gives the namespace into which a Helm chart is installed (note: using impersonation) |
|
||||
| | `.spec.storageNamespace` | This gives the namespace in which the record of a Helm install is created (note: using impersonation) |
|
||||
| | `.spec.chart.spec.sourceRef` | This is a reference (in the created `HelmChart` object) that can include a namespace |
|
||||
| **`alerts.notification.toolkit.fluxcd.io/v1beta1`** | `.spec.eventSources` | Items are references that can include a namespace |
|
||||
| **`receivers.notification.toolkit.fluxcd.io/v1beta1`** | `.spec.resources` | Items in this field are references that can include a namespace |
|
||||
| **`alerts.notification.toolkit.fluxcd.io/v1beta2`** | `.spec.eventSources` | Items are references that can include a namespace |
|
||||
| **`receivers.notification.toolkit.fluxcd.io/v1beta2`** | `.spec.resources` | Items in this field are references that can include a namespace |
|
||||
| **`imagepolicies.image.toolkit.fluxcd.io/v1beta1`** | `.spec.imageRepositoryRef` | This reference can include a namespace[1] |
|
||||
|
||||
[1] This particular cross-namespace reference is subject to additional access control; see "Access
|
||||
|
||||
219
rfcs/0004-insecure-http/README.md
Normal file
219
rfcs/0004-insecure-http/README.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# RFC-0004 Block insecure HTTP connections across Flux
|
||||
|
||||
**Status:** implementable
|
||||
|
||||
**Creation Date:** 2022-09-08
|
||||
|
||||
**Last update:** 2022-10-21
|
||||
|
||||
## Summary
|
||||
|
||||
Flux should have a consistent way of disabling insecure HTTP connections.
|
||||
|
||||
At the controller level, a flag should be present which would disable all outgoing HTTP connections.
|
||||
At the object level, a field should be provided which would enable the use of non-TLS endpoints.
|
||||
|
||||
If the use of a non-TLS endpoint is not supported, reconciliation will fail and the object will be marked
|
||||
as stalled, signalling that human intervention is required.
|
||||
|
||||
## Motivation
|
||||
|
||||
Today the use of non-TLS based connections is inconsistent across Flux controllers.
|
||||
|
||||
Controllers that deal only with `http` and `https` schemes have no way to block use of the `http` scheme at controller-level.
|
||||
Some Flux objects provide a `.spec.insecure` field to enable the use of non-TLS based endpoints, but they don't clearly notify
|
||||
users when the option is not supported (e.g. Azure/GCP Buckets).
|
||||
|
||||
### Goals
|
||||
|
||||
* Provide a flag across relevant Flux controllers which disables all outgoing HTTP connections.
|
||||
* Add a field which enables the use of non-TLS endpoints to appropriate Flux objects.
|
||||
* Provide a way for users to be made aware that their use of non-TLS endpoints is not supported if that is the case.
|
||||
|
||||
### Non-Goals
|
||||
|
||||
* Break Flux's current behavior of allowing HTTP connections.
|
||||
* Change in behavior of communication between Flux components.
|
||||
|
||||
## Proposal
|
||||
|
||||
### Controllers
|
||||
|
||||
Flux users should be able to enforce that controllers are using HTTPS connections only.
|
||||
This shall be enabled by adding a new boolean flag `--insecure-allow-http` to the following controllers:
|
||||
* source-controller
|
||||
* notification-controller
|
||||
* image-automation-controller
|
||||
* image-reflector-controller
|
||||
|
||||
The default value of this flag shall be `true`. This would ensure that there is no breaking change with controllers
|
||||
still being able to access non-TLS endpoints. To disable this behavior and enforce the use of HTTPS connections, users would
|
||||
have to explicitly pass the flag to the controller:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
image: fluxcd/source-controller
|
||||
args:
|
||||
- --watch-all-namespaces
|
||||
- --log-level=info
|
||||
- --log-encoding=json
|
||||
- --enable-leader-election
|
||||
- --storage-path=/data
|
||||
- --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.cluster.local.
|
||||
- --insecure-allow-http=false
|
||||
```
|
||||
|
||||
**Note:** The flag shall not be added to the following controllers:
|
||||
* kustomize-controller: This flag is excluded from this controller, as the upstream `kubenetes-sigs/kustomize` project
|
||||
does not support disabling HTTP connections while fetching resources from remote bases. We can revisit this if the
|
||||
upstream project adds support for this at a later point in time.
|
||||
* helm-controller: This flag does not serve a purpose in this controller, as the controller does not make any HTTP calls.
|
||||
Furthermore although both controllers can also do remote applies, serving `kube-apiserver` over plain
|
||||
HTTP is disabled by default. While technically this can be enabled, the option for this configuration was also disabled
|
||||
quite a while back (ref: https://github.com/kubernetes/kubernetes/pull/65830/).
|
||||
|
||||
### Objects
|
||||
|
||||
Some Flux objects, like `GitRepository`, provide a field for specifying a URL, and the URL would contain the scheme.
|
||||
In such cases, the scheme can be used for inferring the transport type of the connection and consequently,
|
||||
whether to use HTTP or HTTPS connections for that object.
|
||||
But there are a few objects that don't allow such behavior, for example:
|
||||
|
||||
* `ImageRepository`: It provides a field, `.spec.image`, which is used for specifying the address of the image present on
|
||||
a container registry. But any address containing a scheme is considered invalid and HTTPS is the default transport used.
|
||||
This prevents users from using images present on insecure registries.
|
||||
* OCI `HelmRepository`: When using an OCI registry as a Helm repository, the `.spec.url` is expected to begin with `oci://`.
|
||||
Since the scheme part of the URL is used to specify the type of `HelmRepository`, there is no way for users to specify
|
||||
that the registry is hosted at a non-TLS endpoint.
|
||||
|
||||
For such objects, we shall introduce a new boolean field `.spec.insecure`, which shall be `false` by default. Users that
|
||||
need their object to point to an HTTP endpoint, can set this to `true`.
|
||||
|
||||
### CLI
|
||||
|
||||
The Flux CLI offers several commands for creating Flux specific resources. Some of these commands may involve specifying
|
||||
an endpoint such as creating an `OCIRepository`:
|
||||
|
||||
```sh
|
||||
flux create source oci podinfo \
|
||||
--url=oci://ghcr.io/stefanprodan/manifests/podinfo \
|
||||
--tag=6.1.6 \
|
||||
--interval=10m
|
||||
```
|
||||
|
||||
Since these commands essentially create object definitions, the CLI should offer a boolean flag `--insecure`
|
||||
for the required commands, which will be used for specifying the value of `.spec.insecure` of such objects.
|
||||
|
||||
> Note: This flag should not be confused with `--insecure-skip-tls-verify` which is meant to skip TLS verification
|
||||
> when using an HTTPS connection.
|
||||
|
||||
### Precedence & Validity
|
||||
|
||||
Objects with `.spec.insecure` as `true ` will only be allowed if HTTP connections are allowed at the controller level.
|
||||
Similarly, an object can have `.spec.insecure` as `true` only if the Saas/Cloud provider allows HTTP connections.
|
||||
For example, using a `Bucket` with its `.spec.provider` set to `azure` would be invalid since Azure doesn't allow
|
||||
HTTP connections.
|
||||
|
||||
### User Stories
|
||||
|
||||
#### Story 1
|
||||
|
||||
> As a cluster admin of a multi-tenant cluster, I want to ensure all controllers access endpoints using only HTTPS
|
||||
> regardless of tenants' object definitions.
|
||||
|
||||
Apply a `kustomize` patch which prevents the use of HTTP connections:
|
||||
|
||||
```yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patches:
|
||||
- patch: |
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/args/-
|
||||
value: --insecure-allow-http=false
|
||||
target:
|
||||
kind: Deployment
|
||||
name: "(source-controller|notification-controller|image-reflector-controller|image-automation-controller)"
|
||||
# Since the above flag is not available in kustomize-controller for reasons explained in a previous section,
|
||||
# we disable Kustomize remote builds by disallowing use of remote bases. This ensures that kustomize-controller
|
||||
# won't initiate any plain HTTP connections.
|
||||
- patch: |
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/args/-
|
||||
value: --no-remote-bases=true
|
||||
target:
|
||||
kind: Deployment
|
||||
name: kustomize-controller
|
||||
```
|
||||
|
||||
#### Story 2
|
||||
|
||||
> As an application developer, I'm trying to debug a new image pushed to my local registry which
|
||||
> is not served over HTTPS.
|
||||
|
||||
Modify the object spec to use HTTP connections explicitly:
|
||||
```yaml
|
||||
apiVersion: image.toolkit.fluxcd.io/v1beta1
|
||||
kind: ImageRepository
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: flux-system
|
||||
spec:
|
||||
image: kind-registry:5000/stefanprodan/podinfo
|
||||
interval: 1m0s
|
||||
insecure: true
|
||||
```
|
||||
|
||||
### Alternatives
|
||||
|
||||
Instead of adding a flag, we can instruct users to make use of Kyverno policies to enforce that
|
||||
all objects have `.spec.insecure` as `false` and any URLs present in the definition don't have `http`
|
||||
as the scheme. This is less attractive, as this would ask users to install another software and prevent
|
||||
Flux multi-tenancy from being standalone.
|
||||
|
||||
## Design Details
|
||||
|
||||
If a controller is started with `--insecure-allow-http=false`, any URL in a Flux object which has `http`
|
||||
as the scheme will result in an unsuccessful reconciliation and the following condition will be added to the object's
|
||||
`.status.conditions`:
|
||||
|
||||
```yaml
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2022-09-06T09:14:21Z"
|
||||
message: "Use of insecure HTTP connections isn't allowed for this controller"
|
||||
observedGeneration: 1
|
||||
reason: InsecureConnectionsDisallowed
|
||||
status: "True"
|
||||
type: Stalled
|
||||
```
|
||||
|
||||
Similarly, if an object has `.spec.insecure` as `true` but the Cloud provider doesn't allow HTTP connections,
|
||||
the reconciliation will fail and the following condition will be added to the object's `.status.conditions`:
|
||||
|
||||
```yaml
|
||||
status:
|
||||
conditions:
|
||||
- lastTransitionTime: "2022-09-06T09:14:21Z"
|
||||
message: "Use of insecure HTTP connections isn't allowed for Azure Storage"
|
||||
observedGeneration: 1
|
||||
reason: UnsupportedConnectionType
|
||||
status: "True"
|
||||
type: Stalled
|
||||
```
|
||||
|
||||
If an object has `.spec.insecure` as `true`, the registry client or bucket client shall be created with the use
|
||||
of HTTP connections enabled explicitly.
|
||||
|
||||
## Implementation History
|
||||
|
||||
**2022-08-12** Allow defining OCI sources for non-TLS container registries with `flux create source oci --insecure`
|
||||
released with [flux2 v0.34.0](https://github.com/fluxcd/flux2/releases/tag/v0.34.0)
|
||||
|
||||
362
rfcs/0005-artifact-revision-and-digest/README.md
Normal file
362
rfcs/0005-artifact-revision-and-digest/README.md
Normal file
@@ -0,0 +1,362 @@
|
||||
# RFC-0005 Artifact `Revision` format and introduction of `Digest`
|
||||
|
||||
**Status:** implementable
|
||||
|
||||
**Creation date:** 2022-10-20
|
||||
|
||||
**Last update:** 2022-11-16
|
||||
|
||||
## Summary
|
||||
|
||||
This RFC proposes to establish a canonical `Revision` format for an `Artifact`
|
||||
which points to a specific revision represented as a checksum (e.g. an OCI
|
||||
manifest digest or Git commit SHA) of a named pointer (e.g. an OCI repository
|
||||
name or Git tag). In addition, it proposes to include the algorithm name (e.g.
|
||||
`sha256`) as a prefix to an advertised checksum for an `Artifact` and
|
||||
further referring to it as a `Digest`, deprecating the `Checksum` field.
|
||||
|
||||
## Motivation
|
||||
|
||||
The current `Artifact` type's `Revision` field format is not "officially"
|
||||
standardized (albeit assumed throughout our code bases), and has mostly been
|
||||
derived from `GitRepository` which uses `/` as a separator between the named
|
||||
pointer (a Git branch or tag) and a specific (SHA-1, or theoretical SHA-256)
|
||||
revision.
|
||||
|
||||
Since the introduction of `OCIRepository` and with the recent changes around
|
||||
`HelmChart` objects to allow the consumption of charts from OCI registries,
|
||||
this could be seen as outdated or confusing due to the format differing from
|
||||
the canonical format used by OCI, which is `<name>@<algo>:<checksum>` (the
|
||||
part after `@` formally known as a ["digest"][digest-spec]) to refer to a
|
||||
specific version of an OCI manifest.
|
||||
|
||||
While also taking note that Git does not have an official canonical format for
|
||||
e.g. branch references at a specific commit, and `/` has less of a symbolic
|
||||
meaning than `@`, which could be interpreted as "`<branch>` _at_
|
||||
`<commit SHA>`".
|
||||
|
||||
In addition, with the introduction of algorithm prefixes for an `Artifact`'s
|
||||
checksum, it would be possible to add support and allow user configuration of
|
||||
other algorithms than SHA-256. For example SHA-384 and SHA-512, or the more
|
||||
performant (parallelizable) [BLAKE3][].
|
||||
|
||||
Besides this, it would make it easier to implement a client that can verify the
|
||||
checksum without having to resort to an assumed format or guessing
|
||||
method based on the length of it, and allows for a more robust solution in
|
||||
which it can continue to calculate against the algorithm of a previous
|
||||
configuration.
|
||||
|
||||
The inclusion of the `Artifact`'s algorithm prefix has been proposed before in
|
||||
[source-controller#855](https://github.com/fluxcd/source-controller/issues/855),
|
||||
with supportive response from Core Maintainers.
|
||||
|
||||
### Goals
|
||||
|
||||
- Establish a canonical format to refer to an `Artifact`'s `Revision` field
|
||||
which consists of a named pointer and a specific checksum reference.
|
||||
- Allow easier verification of the `Artifact`'s checksum by including an
|
||||
alias for the algorithm.
|
||||
- Deprecate the `Artifact`'s `Checksum` field in favor of the `Digest` field.
|
||||
- Allow configuration of the algorithm used to calculate the checksum of an
|
||||
`Artifact`.
|
||||
- Allow configuration of algorithms other than SHA-256 to calculate the
|
||||
`Digest` of an `Artifact`.
|
||||
- Allow compatibility with SemVer name references which might contain an `@`
|
||||
symbol already (e.g. `package@v1.0.0@sha256:...`, as opposed to OCI's
|
||||
`name:v1.0.0@sha256:...`).
|
||||
|
||||
### Non-Goals
|
||||
|
||||
- Define a canonical format for an `Artifact`'s `Revision` field which contains
|
||||
a named pointer and a different reference than a checksum.
|
||||
|
||||
## Proposal
|
||||
|
||||
### Establish an Artifact Revision format
|
||||
|
||||
Change the format of the `Revision` field of the `source.toolkit.fluxcd.io`
|
||||
Group's `Artifact` type across all `Source` kinds to contain an `@` separator
|
||||
opposed to `/`, and include the algorithm alias as a prefix to the checksum
|
||||
(creating a "digest").
|
||||
|
||||
```text
|
||||
[ <named pointer> ] [ [ "@" ] <algo> ":" <checksum> ]
|
||||
```
|
||||
|
||||
Where `<named pointer>` is the name of e.g. a Git branch or OCI repository
|
||||
name, `<checksum>` is the exact revision (e.g. a Git commit SHA or OCI manifest
|
||||
digest), and `<algo>` is the alias of the algorithm used to calculate the
|
||||
checksum (e.g. `sha256`). In case only a named pointer or digest is advertised,
|
||||
the `@` is omitted.
|
||||
|
||||
For a `GitRepository`'s `Artifact` pointing towards an SHA-1 Git commit on
|
||||
branch `main`, the `Revision` field value would become:
|
||||
|
||||
```text
|
||||
main@sha1:1eabc9a41ca088515cab83f1cce49eb43e84b67f
|
||||
```
|
||||
|
||||
For a `GitRepository`'s `Artifact` pointing towards a specific SHA-1 Git commit
|
||||
without a defined branch or tag, the `Revision` field value would become:
|
||||
|
||||
```text
|
||||
sha1:1eabc9a41ca088515cab83f1cce49eb43e84b67f
|
||||
```
|
||||
|
||||
For a `Bucket`'s `Artifact` with a revision based on an SHA-256 calculation of
|
||||
a list of object keys and their etags, the `Revision` field value would become:
|
||||
|
||||
```text
|
||||
sha256:8fb62a09c9e48ace5463bf940dc15e85f525be4f230e223bbceef6e13024110c
|
||||
```
|
||||
|
||||
For a `HelmChart`'s `Artifact` pointing towards a Helm chart version, the
|
||||
`Revision` field value would become:
|
||||
|
||||
```text
|
||||
1.2.3
|
||||
```
|
||||
|
||||
### Introduce a `Digest` field
|
||||
|
||||
Introduce a new field to the `source.toolkit.fluxcd.io` Group's `Artifact` type
|
||||
across all `Source` kinds called `Digest`, containing the checksum of the file
|
||||
advertised in the `Path`, and alias of the algorithm used to calculate it
|
||||
(creating a ["digest"][digest-spec]).
|
||||
|
||||
```text
|
||||
<algo> ":" <checksum>
|
||||
```
|
||||
|
||||
For a `GitRepository` `Artifact`'s checksum calculated using SHA-256, the
|
||||
`Digest` field value would become:
|
||||
|
||||
```text
|
||||
sha256:1111f92aba67995f108b3ee3ffdc00edcfe206b11fbbb459c8ef4c4a8209fca8
|
||||
```
|
||||
|
||||
#### Deprecate the `Checksum` field
|
||||
|
||||
In favor of the `Digest` field, the `Checksum` field of the `source.toolkit.fluxcd.io`
|
||||
Group's `Artifact` type across all `Source` kinds is deprecated, and removed in
|
||||
a future version.
|
||||
|
||||
### User Stories
|
||||
|
||||
#### Artifact revision verification
|
||||
|
||||
> As a user of the source-controller, I want to be able to see the exact
|
||||
> revision of an Artifact that is being used, so that I can verify that it
|
||||
> matches the expected revision at a remote source.
|
||||
|
||||
For a Source kind that has an `Artifact` with a `Revision` which contains a
|
||||
checksum, the field value can be retrieved using the Kubernetes API. For
|
||||
example:
|
||||
|
||||
```console
|
||||
$ kubectl get gitrepository -o jsonpath='{.status.artifact.revision}' <name>
|
||||
main@sha1:1eabc9a41ca088515cab83f1cce49eb43e84b67f
|
||||
```
|
||||
|
||||
#### Artifact checksum verification
|
||||
|
||||
> As a user of the source-controller, I want to be able to verify the checksum
|
||||
> of an Artifact.
|
||||
|
||||
For a Source kind with an `Artifact` the digest consisting of the algorithm
|
||||
alias and checksum is advertised in the `Digest` field, and can be retrieved
|
||||
using the Kubernetes API. For example:
|
||||
|
||||
```console
|
||||
$ kubectl get gitrepository -o jsonpath='{.status.artifact.digest}' <name>
|
||||
sha256:1111f92aba67995f108b3ee3ffdc00edcfe206b11fbbb459c8ef4c4a8209fca8
|
||||
```
|
||||
|
||||
#### Artifact checksum algorithm configuration
|
||||
|
||||
> As a user of the source-controller, I want to be able to configure the
|
||||
> algorithm used to calculate the checksum of an Artifact.
|
||||
|
||||
The source-controller binary accepts a `--artifact-digest-algo` flag which
|
||||
configures the algorithm used to calculate the checksum of an `Artifact`.
|
||||
The default value is `sha256`, but can be changed to `sha384`, `sha512`
|
||||
or `blake3`.
|
||||
|
||||
When set, newly advertised `Artifact`'s `Digest` fields will be calculated
|
||||
using the configured algorithm. For previous `Artifact`'s that were set using
|
||||
a previous configuration, the `Artifact`'s `Digest` field will be recalculated
|
||||
using the advertised algorithm.
|
||||
|
||||
#### Artifact revisions in notifications
|
||||
|
||||
> As a user of the notification-controller, I want to be able to see the
|
||||
> exact revision a notification is referring to.
|
||||
|
||||
The notification-controller can use the revision for a Source's `Artifact`
|
||||
attached as an annotation to an `Event`, and correctly parses the value field
|
||||
when attempting to extract e.g. a Git commit digest from an event for a
|
||||
`GitRepository`. As currently already applicable for the `/` separator.
|
||||
|
||||
> As a user of the notification-controller, I want to be able to observe what
|
||||
> commit has been applied on my (supported) Git provider.
|
||||
|
||||
The notification-controller can use the revision attached as an annotation to
|
||||
an `Event`, and is capable of extracting the correct reference for a Git
|
||||
provider integration (e.g. GitHub, GitLab) to construct a payload. For example,
|
||||
extracting `1eabc9a41ca088515cab83f1cce49eb43e84b67f` from
|
||||
`main@sha1:1eabc9a41ca088515cab83f1cce49eb43e84b67f`.
|
||||
|
||||
#### Artifact revisions in listed views
|
||||
|
||||
> As a Flux CLI user, I want to see the current revision of my Source in a
|
||||
> listed overview.
|
||||
|
||||
By running `flux get source <kind>`, the listed view of Sources would show a
|
||||
truncated version of the checksum in the `Revision` field.
|
||||
|
||||
```console
|
||||
$ flux get source gitrepository
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
flux-monitoring main@sha1:1eabc9a4 False True stored artifact for revision 'main@sha1:1eabc9a41ca088515cab83f1cce49eb43e84b67f'
|
||||
|
||||
$ flux get source oci
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
apps-source local@sha256:e5fa481b False True stored artifact for digest 'local@sha256:e5fa481bb17327bd269927d0a223862d243d76c89fe697ea8c9adefc47c47e17'
|
||||
|
||||
$ flux get source bucket
|
||||
NAME REVISION SUSPENDED READY MESSAGE
|
||||
apps-source sha256:e3b0c442 False True stored artifact for revision 'sha256:8fb62a09c9e48ace5463bf940dc15e85f525be4f230e223bbceef6e13024110c'
|
||||
```
|
||||
|
||||
### Alternatives
|
||||
|
||||
The two main alternatives around the `Revision` parts in this RFC are to either
|
||||
keep the current field value formats as is, or to invent another format. Given
|
||||
the [motivation](#motivation) for this RFC outlines the reasoning for not
|
||||
keeping the current `Revision` format, and the proposed is a commonly known
|
||||
format. Neither strike as a better alternative.
|
||||
|
||||
For the changes related to `Checksum` and `Digest`, the alternative is to keep
|
||||
the current field name as is, and only change the field value format. However,
|
||||
given the naming of the field is more accurate with the introduction of the
|
||||
algorithm alias, and now is the time to make last (breaking) changes to the
|
||||
API. This does not strike as a better alternative.
|
||||
|
||||
## Design Details
|
||||
|
||||
### Artifact Revision format
|
||||
|
||||
For an `Artifact`'s `Revision` which contains a checksum referring to an exact
|
||||
revision, the checksum within the value MUST be appended with an alias for the
|
||||
algorithm separated by `:` (e.g. `sha256:...`), further referred to as a
|
||||
"digest". The algorithm alias and checksum of the digest MUST be lowercase and
|
||||
alphanumeric.
|
||||
|
||||
For an `Artifact`'s `Revision` which contains a digest and a named pointer,
|
||||
it MUST be prefixed with `@`, and appended at the end of the `Revision` value.
|
||||
The named pointer MAY contain arbitrary characters, including but not limited
|
||||
to `/` and `@`.
|
||||
|
||||
#### Format
|
||||
|
||||
```text
|
||||
[ <named pointer> ] [ [ "@" ] <algo> ":" <checksum> ]
|
||||
```
|
||||
|
||||
Where `[ ]` indicates an optional element, `" "` a literal string, and `< >`
|
||||
a variable.
|
||||
|
||||
#### Parsing
|
||||
|
||||
When parsing the `Revision` field value of an `Artifact` to extract the digest,
|
||||
the value after the last `@` is considered to be the digest. The remaining
|
||||
value on the left side is considered to be the named pointer, which MAY contain
|
||||
an additional `@` separator if applicable for the domain of the `Source`
|
||||
implementation.
|
||||
|
||||
#### Truncation
|
||||
|
||||
When truncating the `Revision` field value of an `Artifact` to display in a
|
||||
view with limited space, the `<checksum>` of the digest MAY be truncated to
|
||||
7 or more characters. The `<algo>` of the digest MUST NOT be truncated.
|
||||
In addition, a digest MUST always contain the full length checksum for the
|
||||
algorithm.
|
||||
|
||||
#### Backwards compatibility
|
||||
|
||||
To allow backwards compatability in the notification-controller, Flux CLI and
|
||||
other applicable components, the `Revision` new field value format could be
|
||||
detected by the presence of the `@` or `:` characters. Falling back to their
|
||||
current behaviour if not present, phasing out the old format in a future
|
||||
release.
|
||||
|
||||
### Artifact Digest
|
||||
|
||||
The `Artifact`'s `Digest` field advertises the checksum of the file in the
|
||||
`URL`. The checksum within the value MUST be appended with an alias for the
|
||||
algorithm separated by `:` (e.g. `sha256:...`). This follows the
|
||||
[digest format][go-digest] of OCI.
|
||||
|
||||
#### Format
|
||||
|
||||
```text
|
||||
<algo> ":" <checksum>
|
||||
```
|
||||
|
||||
Where `" "` indicates a literal string, and `< >` a variable.
|
||||
|
||||
#### Library
|
||||
|
||||
The library used for calculating the `Digest` field value is
|
||||
`github.com/opencontainers/go-digest`. This library is stable and extensible,
|
||||
and used by various OCI libraries which we already depend on.
|
||||
|
||||
#### Calculation
|
||||
|
||||
The checksum in the `Digest` field value MUST be calculated using the canonical
|
||||
algorithm [set at runtime](#configuration).
|
||||
|
||||
#### Configuration
|
||||
|
||||
The algorithm used for calculating the `Digest` field value MAY be configured
|
||||
using the `--artifact-digest-algo` flag of the source-controller binary. The
|
||||
default value is `sha256`, but can be changed to `sha384`, `sha512` or
|
||||
`blake3`.
|
||||
|
||||
**Note:** availability of BLAKE3 is at present dependent on an explicit import
|
||||
of `github.com/opencontainers/go-digest/blake3`.
|
||||
|
||||
When the provided algorithm is NOT supported, the source-controller MUST
|
||||
fail to start.
|
||||
|
||||
When the configured algorithm changes, the `Digest` MAY be recalculated to
|
||||
update the value.
|
||||
|
||||
#### Verification
|
||||
|
||||
The checksum of a downloaded artifact MUST be verified against the `Digest`
|
||||
field value. If the checksum does not match, the verification MUST fail.
|
||||
|
||||
### Deprecation of Checksum
|
||||
|
||||
The `Artifact`'s `Checksum` field is deprecated and MUST be removed in a
|
||||
future release. The `Digest` field MUST be used instead.
|
||||
|
||||
#### Backwards compatibility
|
||||
|
||||
To allow backwards compatability, the source-controller could continue
|
||||
to advertise the checksum part of a `Digest` in the `Checksum` field until
|
||||
the field is removed.
|
||||
|
||||
## Implementation History
|
||||
|
||||
<!--
|
||||
Major milestones in the lifecycle of the RFC such as:
|
||||
- The first Flux release where an initial version of the RFC was available.
|
||||
- The version of Flux where the RFC graduated to general availability.
|
||||
- The version of Flux where the RFC was retired or superseded.
|
||||
-->
|
||||
|
||||
[BLAKE3]: https://github.com/BLAKE3-team/BLAKE3
|
||||
[digest-spec]: https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests
|
||||
[go-digest]: https://pkg.go.dev/github.com/opencontainers/go-digest#hdr-Basics
|
||||
@@ -1,31 +1,35 @@
|
||||
# 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.
|
||||
The test suite goal is to verify that Flux integration with Azure services are working properly.
|
||||
|
||||
## Architecture
|
||||
|
||||
The tests are run with the help of pre-configured Azure subscriptions and Azure DevOps organization. Access to those accounts are currently limited to
|
||||
Flux maintainers.
|
||||
The tests are run with the help of pre-configured Azure subscriptions and Azure DevOps organization.
|
||||
Access to those 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)
|
||||
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 cannot 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 [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 cannot 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
|
||||
a 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 [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 initiated 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 offset to
|
||||
Each test run is initiated by running `terraform apply` on the aks Terraform, it does this by using the library
|
||||
[terraform-exec](https://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 offset to
|
||||
Terraform instead of requiring it to be implemented in the test.
|
||||
|
||||
The following tests are currently implemented:
|
||||
@@ -41,11 +45,13 @@ The following tests are currently implemented:
|
||||
|
||||
## 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.
|
||||
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
|
||||
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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user