Compare commits
66 Commits
release/v2
...
RFC
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ecbad956d | ||
|
|
229d40cc93 | ||
|
|
1e7dc1b392 | ||
|
|
127a742db0 | ||
|
|
43437bf2d5 | ||
|
|
a3038865be | ||
|
|
8fdfbcd251 | ||
|
|
2460a79026 | ||
|
|
9c06883ccf | ||
|
|
b326e5616b | ||
|
|
a30020a6d6 | ||
|
|
dfdfe45b5b | ||
|
|
976f40b642 | ||
|
|
adb77740b5 | ||
|
|
5e14014e37 | ||
|
|
475bcb63b5 | ||
|
|
cccb044dd1 | ||
|
|
cdbad4d946 | ||
|
|
933cf9db02 | ||
|
|
40bf47f41a | ||
|
|
1a0d931ab5 | ||
|
|
779156cf9a | ||
|
|
2726da5b85 | ||
|
|
09b157d74c | ||
|
|
145fd1c2f2 | ||
|
|
33e9a89305 | ||
|
|
417e3d02d1 | ||
|
|
ba555de7da | ||
|
|
83450ab1d2 | ||
|
|
1296b4d16b | ||
|
|
2924af5074 | ||
|
|
2a8492a053 | ||
|
|
94c9b13fbd | ||
|
|
1532687191 | ||
|
|
128301199d | ||
|
|
fbce734ab6 | ||
|
|
3294c7c008 | ||
|
|
20fbcfadac | ||
|
|
4b0cda68b1 | ||
|
|
b91a185641 | ||
|
|
954e682da8 | ||
|
|
3f3009e507 | ||
|
|
b93d4a4a17 | ||
|
|
d321644e30 | ||
|
|
4f20be427e | ||
|
|
b4b0eee142 | ||
|
|
2935bea6a2 | ||
|
|
2bf80d8644 | ||
|
|
284dfc05c6 | ||
|
|
4a97a13300 | ||
|
|
9db8c4a990 | ||
|
|
eafbb753da | ||
|
|
0e75d96911 | ||
|
|
3ae3327a13 | ||
|
|
9ec8e717ae | ||
|
|
a995989961 | ||
|
|
0cf855f16f | ||
|
|
88f973fc56 | ||
|
|
59e5f4c887 | ||
|
|
e0181209c9 | ||
|
|
056189265b | ||
|
|
36adfff99e | ||
|
|
6c45df8c46 | ||
|
|
bf6754e20c | ||
|
|
bae59fde6a | ||
|
|
5ede32b327 |
3
.github/labels.yaml
vendored
3
.github/labels.yaml
vendored
@@ -50,3 +50,6 @@
|
||||
- name: backport:release/v2.1.x
|
||||
description: To be backported to release/v2.1.x
|
||||
color: '#ffd700'
|
||||
- name: backport:release/v2.2.x
|
||||
description: To be backported to release/v2.2.x
|
||||
color: '#ffd700'
|
||||
|
||||
22
.github/runners/README.md
vendored
22
.github/runners/README.md
vendored
@@ -4,16 +4,18 @@ The Flux ARM64 end-to-end tests run on Equinix Metal instances provisioned with
|
||||
|
||||
## Current instances
|
||||
|
||||
| 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 |
|
||||
| Repository | Runner | Instance | Location |
|
||||
|-----------------------------|------------------|----------------|---------------|
|
||||
| flux2 | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC |
|
||||
| flux2 | equinix-arm-dc-2 | flux-arm-dc-01 | Washington DC |
|
||||
| flux2 | equinix-arm-da-1 | flux-arm-da-01 | Dallas |
|
||||
| flux2 | equinix-arm-da-2 | flux-arm-da-01 | Dallas |
|
||||
| flux-benchmark | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC |
|
||||
| flux-benchmark | equinix-arm-da-1 | flux-arm-da-01 | Dallas |
|
||||
| source-controller | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC |
|
||||
| source-controller | equinix-arm-da-1 | flux-arm-da-01 | Dallas |
|
||||
| image-automation-controller | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC |
|
||||
| image-automation-controller | equinix-arm-da-1 | flux-arm-da-01 | Dallas |
|
||||
|
||||
Instance spec:
|
||||
- Ampere Altra Q80-30 80-core processor @ 2.8GHz
|
||||
|
||||
10
.github/runners/prereq.sh
vendored
10
.github/runners/prereq.sh
vendored
@@ -18,11 +18,11 @@
|
||||
|
||||
set -eu
|
||||
|
||||
KIND_VERSION=0.17.0
|
||||
KUBECTL_VERSION=1.24.0
|
||||
KUSTOMIZE_VERSION=4.5.7
|
||||
HELM_VERSION=3.10.1
|
||||
GITHUB_RUNNER_VERSION=2.298.2
|
||||
KIND_VERSION=0.22.0
|
||||
KUBECTL_VERSION=1.29.0
|
||||
KUSTOMIZE_VERSION=5.3.0
|
||||
HELM_VERSION=3.14.1
|
||||
GITHUB_RUNNER_VERSION=2.313.0
|
||||
PACKAGES="apt-transport-https ca-certificates software-properties-common build-essential libssl-dev gnupg lsb-release jq pkg-config"
|
||||
|
||||
# install prerequisites
|
||||
|
||||
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.298.2
|
||||
GITHUB_RUNNER_VERSION=2.313.0
|
||||
|
||||
# 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 \
|
||||
|
||||
47
.github/workflows/e2e-azure.yaml
vendored
47
.github/workflows/e2e-azure.yaml
vendored
@@ -21,7 +21,52 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
e2e-aks:
|
||||
e2e-amd64-aks:
|
||||
runs-on: ubuntu-22.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./tests/azure
|
||||
# This job is currently disabled. Remove the false check when Azure subscription is enabled.
|
||||
if: false && (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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: tests/azure/go.sum
|
||||
- name: Setup Flux CLI
|
||||
run: |
|
||||
make build
|
||||
mkdir -p $HOME/.local/bin
|
||||
mv ./bin/flux $HOME/.local/bin
|
||||
working-directory: ./
|
||||
- name: Setup SOPS
|
||||
run: |
|
||||
mkdir -p $HOME/.local/bin
|
||||
wget https://github.com/mozilla/sops/releases/download/v3.7.1/sops-v3.7.1.linux -O $HOME/.local/bin/sops
|
||||
chmod +x $HOME/.local/bin/sops
|
||||
- name: Setup Terraform
|
||||
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v2
|
||||
with:
|
||||
terraform_version: 1.2.8
|
||||
terraform_wrapper: false
|
||||
- name: Setup Azure CLI
|
||||
run: |
|
||||
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
||||
- name: Run Azure e2e tests
|
||||
env:
|
||||
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
|
||||
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
|
||||
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
|
||||
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
|
||||
run: |
|
||||
ls $HOME/.local/bin
|
||||
az login --service-principal -u ${ARM_CLIENT_ID} -p ${ARM_CLIENT_SECRET} -t ${ARM_TENANT_ID}
|
||||
go test -v -coverprofile cover.out -timeout 60m .
|
||||
|
||||
refactored-e2e-amd64-aks:
|
||||
runs-on: ubuntu-22.04
|
||||
defaults:
|
||||
run:
|
||||
|
||||
3
.github/workflows/scan.yaml
vendored
3
.github/workflows/scan.yaml
vendored
@@ -49,11 +49,10 @@ jobs:
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
continue-on-error: true
|
||||
run: |
|
||||
snyk test --all-projects --sarif-file-output=snyk.sarif
|
||||
snyk test --sarif-file-output=snyk.sarif
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
continue-on-error: true
|
||||
uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
|
||||
1
Makefile
1
Makefile
@@ -18,6 +18,7 @@ all: test build
|
||||
|
||||
tidy:
|
||||
go mod tidy -compat=1.20
|
||||
cd tests/azure && go mod tidy -compat=1.20
|
||||
cd tests/integration && go mod tidy -compat=1.20
|
||||
|
||||
fmt:
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
# :warning: Deprecation Notice
|
||||
# :warning: Removal Notice
|
||||
|
||||
Starting Flux v2.1.0, released August 24, 2023, the Flux monitoring
|
||||
configurations in this repository will be marked as deprecated. New monitoring
|
||||
configurations in this repository were marked as deprecated. The new monitoring
|
||||
docs are available at [Flux monitoring](https://fluxcd.io/flux/monitoring/)
|
||||
docs with new example configurations in
|
||||
[fluxcd/flux2-monitoring-example](https://github.com/fluxcd/flux2-monitoring-example/).
|
||||
The deprecated configurations will be removed in a future release of Flux. All
|
||||
users of these configurations are recommended to use the new monitoring setup,
|
||||
following the docs and the new examples.
|
||||
|
||||
The deprecated configurations were removed in Flux v2.2 on December 13, 2023. All
|
||||
users of these configurations are advised to use the new monitoring setup,
|
||||
following the [docs](https://fluxcd.io/flux/monitoring/) and the
|
||||
[examples](https://github.com/fluxcd/flux2-monitoring-example/).
|
||||
|
||||
After collecting a lot of user feedback about our monitoring recommendation, in
|
||||
order to serve most of the needs of the users, we decided to create a new
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: monitoring
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- repository.yaml
|
||||
- release.yaml
|
||||
@@ -1,6 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: monitoring
|
||||
labels:
|
||||
app.kubernetes.io/component: monitoring
|
||||
@@ -1,51 +0,0 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: kube-prometheus-stack
|
||||
spec:
|
||||
interval: 5m
|
||||
chart:
|
||||
spec:
|
||||
version: "45.x"
|
||||
chart: kube-prometheus-stack
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: prometheus-community
|
||||
interval: 60m
|
||||
install:
|
||||
crds: Create
|
||||
upgrade:
|
||||
crds: CreateReplace
|
||||
# https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/values.yaml
|
||||
values:
|
||||
alertmanager:
|
||||
enabled: false
|
||||
prometheus:
|
||||
prometheusSpec:
|
||||
retention: 24h
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 200Mi
|
||||
podMonitorNamespaceSelector: {}
|
||||
podMonitorSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: monitoring
|
||||
postRenderers:
|
||||
- kustomize:
|
||||
patches:
|
||||
- target:
|
||||
# Ignore these objects from Flux diff as they are mutated from chart hooks
|
||||
kind: (ValidatingWebhookConfiguration|MutatingWebhookConfiguration)
|
||||
name: kube-prometheus-stack-admission
|
||||
patch: |
|
||||
- op: add
|
||||
path: /metadata/annotations/helm.toolkit.fluxcd.io~1driftDetection
|
||||
value: disabled
|
||||
- target:
|
||||
# Ignore these objects from Flux diff as they are mutated at apply time but not at dry-run time
|
||||
kind: PrometheusRule
|
||||
patch: |
|
||||
- op: add
|
||||
path: /metadata/annotations/helm.toolkit.fluxcd.io~1driftDetection
|
||||
value: disabled
|
||||
@@ -1,9 +0,0 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
kind: HelmRepository
|
||||
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
|
||||
@@ -1,6 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: monitoring
|
||||
resources:
|
||||
- repository.yaml
|
||||
- release.yaml
|
||||
@@ -1,40 +0,0 @@
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2beta1
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: loki-stack
|
||||
spec:
|
||||
interval: 5m
|
||||
dependsOn:
|
||||
- name: kube-prometheus-stack
|
||||
chart:
|
||||
spec:
|
||||
version: "2.x"
|
||||
chart: loki-stack
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: grafana-charts
|
||||
interval: 60m
|
||||
# https://github.com/grafana/helm-charts/blob/main/charts/loki-stack/values.yaml
|
||||
# https://github.com/grafana/loki/blob/main/production/helm/loki/values.yaml
|
||||
values:
|
||||
grafana:
|
||||
enabled: false
|
||||
sidecar:
|
||||
datasources:
|
||||
enabled: true
|
||||
maxLines: 1000
|
||||
promtail:
|
||||
enabled: true
|
||||
loki:
|
||||
enabled: true
|
||||
isDefault: false
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
additionalLabels:
|
||||
app.kubernetes.io/part-of: kube-prometheus-stack
|
||||
config:
|
||||
chunk_store_config:
|
||||
max_look_back_period: 0s
|
||||
table_manager:
|
||||
retention_deletes_enabled: true
|
||||
retention_period: 12h
|
||||
@@ -1,7 +0,0 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: grafana-charts
|
||||
spec:
|
||||
interval: 120m0s
|
||||
url: https://grafana.github.io/helm-charts
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,332 +0,0 @@
|
||||
{
|
||||
"__inputs": [
|
||||
{
|
||||
"name": "DS_LOKI",
|
||||
"label": "Loki",
|
||||
"description": "",
|
||||
"type": "datasource",
|
||||
"pluginId": "loki",
|
||||
"pluginName": "Loki"
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"enable": true,
|
||||
"iconColor": "red",
|
||||
"name": "flux events",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [
|
||||
"flux"
|
||||
],
|
||||
"type": "tags"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "Flux logs collected from Kubernetes, stored in Loki",
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": 29,
|
||||
"iteration": 1653748775696,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": "${DS_LOKI}",
|
||||
"description": "",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "bars",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 4,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "hidden",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": "${DS_LOKI}",
|
||||
"expr": "sum(count_over_time({namespace=~\"$namespace\", stream=~\"$stream\", app =~\"$controller\"} | json | __error__!=\"JSONParserErr\" | level=~\"$level\" |= \"$query\" [$__interval]))",
|
||||
"instant": false,
|
||||
"legendFormat": "Log count",
|
||||
"range": true,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": "${DS_LOKI}",
|
||||
"description": "Logs from services running in Kubernetes",
|
||||
"gridPos": {
|
||||
"h": 25,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 4
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"dedupStrategy": "numbers",
|
||||
"enableLogDetails": false,
|
||||
"prettifyLogMessage": true,
|
||||
"showCommonLabels": false,
|
||||
"showLabels": false,
|
||||
"showTime": false,
|
||||
"sortOrder": "Descending",
|
||||
"wrapLogMessage": false
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": "${DS_LOKI}",
|
||||
"expr": "{namespace=~\"$namespace\", stream=~\"$stream\", app =~\"$controller\"} | json | __error__!=\"JSONParserErr\" | level=~\"$level\" |= \"$query\"",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"type": "logs"
|
||||
}
|
||||
],
|
||||
"refresh": "10s",
|
||||
"schemaVersion": 36,
|
||||
"style": "light",
|
||||
"tags": [
|
||||
"flux"
|
||||
],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "",
|
||||
"value": ""
|
||||
},
|
||||
"description": "String to search for",
|
||||
"hide": 0,
|
||||
"label": "Search Query",
|
||||
"name": "query",
|
||||
"options": [
|
||||
{
|
||||
"selected": true,
|
||||
"text": "",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"query": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "textbox"
|
||||
},
|
||||
{
|
||||
"allValue": "info|error",
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "All",
|
||||
"value": "$__all"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"multi": false,
|
||||
"name": "level",
|
||||
"options": [
|
||||
{
|
||||
"selected": true,
|
||||
"text": "All",
|
||||
"value": "$__all"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "info",
|
||||
"value": "info"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "error",
|
||||
"value": "error"
|
||||
}
|
||||
],
|
||||
"query": "info,error",
|
||||
"queryValue": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"allValue": ".+",
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": [
|
||||
"All"
|
||||
],
|
||||
"value": [
|
||||
"$__all"
|
||||
]
|
||||
},
|
||||
"datasource": "${DS_LOKI}",
|
||||
"definition": "label_values(app)",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"multi": true,
|
||||
"name": "controller",
|
||||
"options": [],
|
||||
"query": "label_values(app)",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"type": "query"
|
||||
},
|
||||
{
|
||||
"allValue": ".+",
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": [
|
||||
"flux-system"
|
||||
],
|
||||
"value": [
|
||||
"flux-system"
|
||||
]
|
||||
},
|
||||
"datasource": "${DS_LOKI}",
|
||||
"definition": "label_values(namespace)",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"multi": true,
|
||||
"name": "namespace",
|
||||
"options": [],
|
||||
"query": "label_values(namespace)",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"type": "query"
|
||||
},
|
||||
{
|
||||
"allValue": ".+",
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "All",
|
||||
"value": "$__all"
|
||||
},
|
||||
"datasource": "${DS_LOKI}",
|
||||
"definition": "label_values(stream)",
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"multi": true,
|
||||
"name": "stream",
|
||||
"options": [],
|
||||
"query": "label_values(stream)",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"sort": 0,
|
||||
"type": "query"
|
||||
},
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "Loki",
|
||||
"value": "Loki"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"label": "Datasource",
|
||||
"multi": false,
|
||||
"name": "DS_LOKI",
|
||||
"options": [],
|
||||
"query": "loki",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "Flux Logs",
|
||||
"uid": "flux-logs",
|
||||
"version": 2
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
namespace: monitoring
|
||||
resources:
|
||||
- podmonitor.yaml
|
||||
configMapGenerator:
|
||||
- name: flux-grafana-dashboards
|
||||
files:
|
||||
- dashboards/control-plane.json
|
||||
- dashboards/cluster.json
|
||||
- dashboards/logs.json
|
||||
options:
|
||||
labels:
|
||||
grafana_dashboard: "1"
|
||||
app.kubernetes.io/part-of: flux
|
||||
app.kubernetes.io/component: monitoring
|
||||
@@ -1,30 +0,0 @@
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PodMonitor
|
||||
metadata:
|
||||
name: flux-system
|
||||
namespace: flux-system
|
||||
labels:
|
||||
app.kubernetes.io/part-of: flux
|
||||
app.kubernetes.io/component: monitoring
|
||||
spec:
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- flux-system
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- helm-controller
|
||||
- source-controller
|
||||
- kustomize-controller
|
||||
- notification-controller
|
||||
- image-automation-controller
|
||||
- image-reflector-controller
|
||||
podMetricsEndpoints:
|
||||
- port: http-prom
|
||||
relabelings:
|
||||
# https://github.com/prometheus-operator/prometheus-operator/issues/4816
|
||||
- sourceLabels: [__meta_kubernetes_pod_phase]
|
||||
action: keep
|
||||
regex: Running
|
||||
BIN
rfcs/NNNN-cdevents/CDEvents-Flux-RFC-Adapter.png
Normal file
BIN
rfcs/NNNN-cdevents/CDEvents-Flux-RFC-Adapter.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
BIN
rfcs/NNNN-cdevents/CDEvents-Flux-RFC-Broker.png
Normal file
BIN
rfcs/NNNN-cdevents/CDEvents-Flux-RFC-Broker.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 731 KiB |
BIN
rfcs/NNNN-cdevents/Flux-CDEvents-RFC.png
Normal file
BIN
rfcs/NNNN-cdevents/Flux-CDEvents-RFC.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
134
rfcs/NNNN-cdevents/README.md
Normal file
134
rfcs/NNNN-cdevents/README.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Flux CDEvents Receiver
|
||||
|
||||
<!--
|
||||
The title must be short and descriptive.
|
||||
-->
|
||||
|
||||
**Status:** provisional
|
||||
|
||||
<!--
|
||||
Status represents the current state of the RFC.
|
||||
Must be one of `provisional`, `implementable`, `implemented`, `deferred`, `rejected`, `withdrawn`, or `replaced`.
|
||||
-->
|
||||
|
||||
**Creation date:** 2023-12-08
|
||||
|
||||
**Last update:** 2024-02-09
|
||||
|
||||
## Summary
|
||||
|
||||
The CDEvents Receiver for Flux receives a CDEvent sent to the receiver webhook URL, verifies it and checks the event type against `.spec.events`, then triggers reconciliation of the configured resources.
|
||||
<!--
|
||||
One paragraph explanation of the proposed feature or enhancement.
|
||||
-->
|
||||
|
||||
## Motivation
|
||||
|
||||
CDEvents enables interoperability between supported tools in a workflow, and flux is a very popular continuous delivery tool, as such we have received many questions about implementing CDEvents into the tool.
|
||||
<!--
|
||||
This section is for explicitly listing the motivation, goals, and non-goals of
|
||||
this RFC. Describe why the change is important and the benefits to users.
|
||||
-->
|
||||
|
||||
### Goals
|
||||
|
||||
Integrate CDEvents into Flux with a CDEvents Receiver.
|
||||
<!--
|
||||
List the specific goals of this RFC. What is it trying to achieve? How will we
|
||||
know that this has succeeded?
|
||||
-->
|
||||
|
||||
### Non-Goals
|
||||
|
||||
A CDEvent provider will be handled as a separate RFC in the future.
|
||||
|
||||
<!--
|
||||
What is out of scope for this RFC? Listing non-goals helps to focus discussion
|
||||
and make progress.
|
||||
-->
|
||||
|
||||
## Proposal
|
||||
|
||||
Add CDEvents to the list of available receivers in Flux Notification controller. Similar to other receivers such as the github, the user will be able to use `spec.events` in order to specify which event types the receiver will allow. The receiver will also verify using the [CDEvents Go SDK](https://github.com/cdevents/sdk-go) that the payload sent to the webhook URL is a valid CDEvent.
|
||||
|
||||
<!--
|
||||
This is where we get down to the specifics of what the proposal actually is.
|
||||
This should have enough detail that reviewers can understand exactly what
|
||||
you're proposing, but should not include things like API designs or
|
||||
implementation.
|
||||
|
||||
If the RFC goal is to document best practices,
|
||||
then this section can be replaced with the actual documentation.
|
||||
-->
|
||||
|
||||
### User Stories
|
||||
|
||||
<!--
|
||||
Optional if existing discussions and/or issues are linked in the motivation section.
|
||||
-->
|
||||
|
||||
|
||||
Using Tekton the user triggers something that will fire off a CDEvent to the CloudEvents Broker. A subscription that the user will have set up externally will then send a relevant CDEvent to the CDEvent Receiver within Flux based on the configuration.
|
||||
|
||||

|
||||
|
||||
### Alternatives
|
||||
|
||||
Certain use cases for CDEvents could be done alternatively using available receivers such as the generic webhook.
|
||||
|
||||
<!--
|
||||
List plausible alternatives to the proposal and explain why the proposal is superior.
|
||||
|
||||
This is a good place to incorporate suggestions made during discussion of the RFC.
|
||||
-->
|
||||
|
||||
## Design Details
|
||||
|
||||
Adding a receiver for CDEvents that works much like the other event-based receivers already implemented. The user will be able to write a yaml file for the receiver and deploy it to their cluster. The receiver takes the payload sent to the webhook URL by an external events broker, checks the headers for the event type, and filters out events based on the user-defined list of events in spec.Events. If left empty, it will act on all valid CDEvents. It then validates the payload body using the [CDEvents Go SDK](https://github.com/cdevents/sdk-go). Valid events will then trigger reconciliation of the resources. The events broker is not a part of this design and is left to the user to set up however they wish.
|
||||
|
||||
Example Receiver YAML:
|
||||
|
||||
```yaml
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1
|
||||
kind: Receiver
|
||||
metadata:
|
||||
name: cdevents-receiver
|
||||
namespace: flux-system
|
||||
spec:
|
||||
type: cdevents
|
||||
events:
|
||||
- "dev.cdevents.change.merged"
|
||||
secretRef:
|
||||
name: receiver-token
|
||||
resources:
|
||||
- kind: GitRespository
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
name: webapp
|
||||
namespace: flux-system
|
||||
```
|
||||
|
||||

|
||||
|
||||
<!--
|
||||
This section should contain enough information that the specifics of your
|
||||
change are understandable. This may include API specs and code snippets.
|
||||
|
||||
The design details should address at least the following questions:
|
||||
- How can this feature be enabled / disabled?
|
||||
- Does enabling the feature change any default behavior?
|
||||
- Can the feature be disabled once it has been enabled?
|
||||
- How can an operator determine if the feature is in use?
|
||||
- Are there any drawbacks when enabling this feature?
|
||||
-->
|
||||
|
||||

|
||||
|
||||
|
||||
## 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.
|
||||
-->
|
||||
BIN
rfcs/NNNN-cdevents/cdevents-flux-tekton.png
Normal file
BIN
rfcs/NNNN-cdevents/cdevents-flux-tekton.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 649 KiB |
57
tests/azure/README.md
Normal file
57
tests/azure/README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Azure E2E
|
||||
|
||||
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.
|
||||
* [Azure Subscription](https://portal.azure.com/#@weaveworksendtoend.onmicrosoft.com/resource/subscriptions/71e8dce4-9af6-405a-8e96-425f5d3c302b/overview)
|
||||
* [Azure DevOps organization](https://dev.azure.com/flux-azure/)
|
||||
|
||||
All infrastructure is and should be created with Terraform. There are two separate Terraform states.
|
||||
All state should be configured to use remote state in Azure.
|
||||
They should all be placed in the [same container](https://portal.azure.com/#@weaveworksendtoend.onmicrosoft.com/resource/subscriptions/71e8dce4-9af6-405a-8e96-425f5d3c302b/resourceGroups/terraform-state/providers/Microsoft.Storage/storageAccounts/terraformstate0419/containersList)
|
||||
but use different keys.
|
||||
|
||||
The [shared](./terraform/shared) Terraform creates long running cheaper infrastructure that is used across all tests.
|
||||
This includes a Key Vault which contains an ssh key and Azure DevOps Personal Access Token
|
||||
which 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 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](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:
|
||||
|
||||
- [x] Flux can be successfully installed on AKS using the CLI e.g.:
|
||||
- [x] source-controller can clone Azure DevOps repositories (https+ssh)
|
||||
- [x] image-reflector-controller can list tags from Azure Container Registry image repositories
|
||||
- [x] kustomize-controller can decrypt secrets using SOPS and Azure Key Vault
|
||||
- [x] image-automation-controller can create branches and push to Azure DevOps repositories (https+ssh)
|
||||
- [x] notification-controller can send commit status to Azure DevOps
|
||||
- [x] notification-controller can forward events to Azure Event Hub
|
||||
- [x] source-controller can pull charts from Azure Container Registry Helm repositories
|
||||
|
||||
## Give User Access
|
||||
|
||||
There are a couple of steps required when adding a new user to get access to the Azure portal and Azure DevOps.
|
||||
To begin with add the new user to[Azure AD](https://portal.azure.com/#blade/Microsoft_AAD_IAM/UsersManagementMenuBlade/MsGraphUsers),
|
||||
and add the user to the [Azure AD group flux-contributors](https://portal.azure.com/#blade/Microsoft_AAD_IAM/GroupDetailsMenuBlade/Overview/groupId/24e0f3f6-6555-4d3d-99ab-414c869cab5d).
|
||||
The new users should now go through the invite process, and be able to sign in to both the Azure Portal and Azure DevOps.
|
||||
|
||||
After the new user has signed into Azure DevOps you will need to modify the users permissions.
|
||||
This cannot be done before the user has signed in a first time.
|
||||
In the [organization users page](https://dev.azure.com/flux-azure/_settings/users)
|
||||
chose "Manage User" and set the "Access Level" to basic
|
||||
and make the user "Project Contributor" of the "e2e" Azure DevOps project.
|
||||
960
tests/azure/azure_test.go
Normal file
960
tests/azure/azure_test.go
Normal file
@@ -0,0 +1,960 @@
|
||||
/*
|
||||
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 test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
b64 "encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
eventhub "github.com/Azure/azure-event-hubs-go/v3"
|
||||
giturls "github.com/chainguard-dev/git-urls"
|
||||
install "github.com/hashicorp/hc-install"
|
||||
"github.com/hashicorp/hc-install/fs"
|
||||
"github.com/hashicorp/hc-install/product"
|
||||
"github.com/hashicorp/hc-install/src"
|
||||
"github.com/hashicorp/terraform-exec/tfexec"
|
||||
"github.com/microsoft/azure-devops-go-api/azuredevops"
|
||||
"github.com/microsoft/azure-devops-go-api/azuredevops/git"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/multierr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/klog/v2/klogr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
runtimeLog "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
automationv1beta1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
reflectorv1beta2 "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
||||
notiv1 "github.com/fluxcd/notification-controller/api/v1"
|
||||
notiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
extgogit "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
)
|
||||
|
||||
const (
|
||||
aksTerraformPath = "./terraform/aks"
|
||||
azureDevOpsKnownHosts = "ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
kubeconfigPath string
|
||||
kubeClient client.Client
|
||||
|
||||
azdoPat string
|
||||
idRsa string
|
||||
idRsaPub string
|
||||
knownHosts string
|
||||
fleetInfraRepository repoConfig
|
||||
applicationRepository repoConfig
|
||||
|
||||
fluxAzureSp spConfig
|
||||
sopsId string
|
||||
acr acrConfig
|
||||
eventHubSas string
|
||||
}
|
||||
|
||||
type spConfig struct {
|
||||
tenantId string
|
||||
clientId string
|
||||
clientSecret string
|
||||
}
|
||||
|
||||
type repoConfig struct {
|
||||
http string
|
||||
ssh string
|
||||
}
|
||||
|
||||
type acrConfig struct {
|
||||
url string
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
var cfg config
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
exitVal, err := setup(m)
|
||||
if err != nil {
|
||||
log.Printf("Received an error while running setup: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(exitVal)
|
||||
}
|
||||
|
||||
func setup(m *testing.M) (exitVal int, err error) {
|
||||
ctx := context.TODO()
|
||||
runtimeLog.SetLogger(klogr.New())
|
||||
// Setup Terraform binary and init state
|
||||
log.Println("Setting up Azure test infrastructure")
|
||||
i := install.NewInstaller()
|
||||
// Find Terraform binary path
|
||||
execPath, err := i.Ensure(ctx, []src.Source{
|
||||
&fs.AnyVersion{Product: &product.Terraform},
|
||||
})
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("terraform exec path not found: %v", err)
|
||||
}
|
||||
tf, err := tfexec.NewTerraform(aksTerraformPath, execPath)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not create terraform instance: %v", err)
|
||||
}
|
||||
log.Println("Init Terraform")
|
||||
err = tf.Init(ctx, tfexec.Upgrade(true))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error running init: %v", err)
|
||||
}
|
||||
|
||||
// Always destroy the infrastructure before exiting
|
||||
defer func() {
|
||||
log.Println("Tearing down Azure test infrastructure")
|
||||
if ferr := tf.Destroy(ctx); ferr != nil {
|
||||
err = multierr.Append(fmt.Errorf("could not destroy Azure infrastructure: %v", ferr), err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Check that we are starting from a clean state
|
||||
log.Println("Checking for an empty Terraform state")
|
||||
state, err := tf.Show(ctx)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not read state: %v", err)
|
||||
}
|
||||
if state.Values != nil {
|
||||
return 0, fmt.Errorf("expected an empty state but got existing resources")
|
||||
}
|
||||
|
||||
// Apply Terraform and read the output values
|
||||
log.Println("Applying Terraform")
|
||||
err = tf.Apply(ctx)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error running apply: %v", err)
|
||||
}
|
||||
state, err = tf.Show(ctx)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not read state: %v", err)
|
||||
}
|
||||
outputs := state.Values.Outputs
|
||||
kubeconfig := outputs["aks_kube_config"].Value.(string)
|
||||
aksHost := outputs["aks_host"].Value.(string)
|
||||
aksCert := outputs["aks_client_certificate"].Value.(string)
|
||||
aksKey := outputs["aks_client_key"].Value.(string)
|
||||
aksCa := outputs["aks_cluster_ca_certificate"].Value.(string)
|
||||
azdoPat := outputs["shared_pat"].Value.(string)
|
||||
idRsa := outputs["shared_id_rsa"].Value.(string)
|
||||
idRsaPub := outputs["shared_id_rsa_pub"].Value.(string)
|
||||
fleetInfraRepository := outputs["fleet_infra_repository"].Value.(map[string]interface{})
|
||||
applicationRepository := outputs["application_repository"].Value.(map[string]interface{})
|
||||
fluxAzureSp := outputs["flux_azure_sp"].Value.(map[string]interface{})
|
||||
sharedSopsId := outputs["sops_id"].Value.(string)
|
||||
acr := outputs["acr"].Value.(map[string]interface{})
|
||||
eventHubSas := outputs["event_hub_sas"].Value.(string)
|
||||
|
||||
// Setup Kubernetes clients for test cluster
|
||||
log.Println("Creating Kubernetes client")
|
||||
kubeconfigPath, kubeClient, err := getKubernetesCredentials(kubeconfig, aksHost, aksCert, aksKey, aksCa)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error create Kubernetes client: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if ferr := os.RemoveAll(filepath.Dir(kubeconfigPath)); ferr != nil {
|
||||
err = multierr.Append(fmt.Errorf("could not clean up kubeconfig file: %v", ferr), err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Install Flux in the new cluster
|
||||
cfg = config{
|
||||
kubeconfigPath: kubeconfigPath,
|
||||
kubeClient: kubeClient,
|
||||
azdoPat: azdoPat,
|
||||
idRsa: idRsa,
|
||||
idRsaPub: idRsaPub,
|
||||
knownHosts: azureDevOpsKnownHosts,
|
||||
fleetInfraRepository: repoConfig{
|
||||
http: fleetInfraRepository["http"].(string),
|
||||
ssh: fleetInfraRepository["ssh"].(string),
|
||||
},
|
||||
applicationRepository: repoConfig{
|
||||
http: applicationRepository["http"].(string),
|
||||
ssh: applicationRepository["ssh"].(string),
|
||||
},
|
||||
fluxAzureSp: spConfig{
|
||||
tenantId: fluxAzureSp["tenant_id"].(string),
|
||||
clientId: fluxAzureSp["client_id"].(string),
|
||||
clientSecret: fluxAzureSp["client_secret"].(string),
|
||||
},
|
||||
sopsId: sharedSopsId,
|
||||
acr: acrConfig{
|
||||
url: acr["url"].(string),
|
||||
username: acr["username"].(string),
|
||||
password: acr["password"].(string),
|
||||
},
|
||||
eventHubSas: eventHubSas,
|
||||
}
|
||||
err = installFlux(ctx, kubeClient, kubeconfigPath, cfg.fleetInfraRepository.http, azdoPat, cfg.fluxAzureSp)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error installing Flux: %v", err)
|
||||
}
|
||||
|
||||
// Run tests
|
||||
log.Println("Running Azure e2e tests")
|
||||
result := m.Run()
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func TestFluxInstallation(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, "flux-system", "flux-system")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 60*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestAzureDevOpsCloning(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
branchName := "feature/branch"
|
||||
tagName := "v1"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
refType string
|
||||
cloneType string
|
||||
}{
|
||||
{
|
||||
name: "https-feature-branch",
|
||||
refType: "branch",
|
||||
cloneType: "http",
|
||||
},
|
||||
{
|
||||
name: "https-v1",
|
||||
refType: "tag",
|
||||
cloneType: "http",
|
||||
},
|
||||
{
|
||||
name: "ssh-feature-branch",
|
||||
refType: "branch",
|
||||
cloneType: "ssh",
|
||||
},
|
||||
{
|
||||
name: "ssh-v1",
|
||||
refType: "tag",
|
||||
cloneType: "ssh",
|
||||
},
|
||||
}
|
||||
|
||||
t.Log("Creating application sources")
|
||||
repo, _, err := getRepository(cfg.applicationRepository.http, branchName, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
files := make(map[string]io.Reader)
|
||||
for _, tt := range tests {
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, tt.name)
|
||||
name := fmt.Sprintf("cloning-test/%s/configmap.yaml", tt.name)
|
||||
files[name] = strings.NewReader(manifest)
|
||||
}
|
||||
|
||||
err = commitAndPushAll(repo, files, branchName)
|
||||
require.NoError(t, err)
|
||||
err = createTagAndPush(repo, branchName, tagName, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log("Verifying application-gitops namespaces")
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ref := &sourcev1.GitRepositoryRef{
|
||||
Branch: branchName,
|
||||
}
|
||||
if tt.refType == "tag" {
|
||||
ref = &sourcev1.GitRepositoryRef{
|
||||
Tag: tagName,
|
||||
}
|
||||
}
|
||||
url := cfg.applicationRepository.http
|
||||
secretData := map[string]string{
|
||||
"username": "git",
|
||||
"password": cfg.azdoPat,
|
||||
}
|
||||
if tt.cloneType == "ssh" {
|
||||
url = cfg.applicationRepository.ssh
|
||||
secretData = map[string]string{
|
||||
"identity": cfg.idRsa,
|
||||
"identity.pub": cfg.idRsaPub,
|
||||
"known_hosts": cfg.knownHosts,
|
||||
}
|
||||
}
|
||||
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: tt.name,
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &namespace, func() error {
|
||||
return nil
|
||||
})
|
||||
gitSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "git-credentials",
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, gitSecret, func() error {
|
||||
gitSecret.StringData = secretData
|
||||
return nil
|
||||
})
|
||||
source := &sourcev1.GitRepository{ObjectMeta: metav1.ObjectMeta{Name: tt.name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, source, func() error {
|
||||
source.Spec = sourcev1.GitRepositorySpec{
|
||||
Reference: ref,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: gitSecret.Name,
|
||||
},
|
||||
URL: url,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: tt.name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec = kustomizev1.KustomizationSpec{
|
||||
Path: fmt.Sprintf("./cloning-test/%s", tt.name),
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: tt.name,
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
Interval: metav1.Duration{Duration: 1 * time.Minute},
|
||||
Prune: true,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for configmap to be deployed
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, namespace.Name, tt.name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
nn := types.NamespacedName{Name: "foobar", Namespace: namespace.Name}
|
||||
cm := &corev1.ConfigMap{}
|
||||
err = cfg.kubeClient.Get(ctx, nn, cm)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 120*time.Second, 5*time.Second)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageRepositoryACR(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "image-repository-acr"
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
oldVersion := "1.0.0"
|
||||
newVersion := "1.0.1"
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: %s
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: podinfo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: podinfo
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: %s/container/podinfo:%s # {"$imagepolicy": "%s:podinfo"}
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- podcli
|
||||
- check
|
||||
- http
|
||||
- localhost:9898/readyz
|
||||
initialDelaySeconds: 5
|
||||
timeoutSeconds: 5`, name, cfg.acr.url, oldVersion, name)
|
||||
|
||||
repo, _, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
files := make(map[string]io.Reader)
|
||||
files["podinfo.yaml"] = strings.NewReader(manifest)
|
||||
err = commitAndPushAll(repo, files, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
acrSecret := corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "acr-docker", Namespace: name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &acrSecret, func() error {
|
||||
acrSecret.Type = corev1.SecretTypeDockerConfigJson
|
||||
acrSecret.StringData = map[string]string{
|
||||
".dockerconfigjson": fmt.Sprintf(`
|
||||
{
|
||||
"auths": {
|
||||
"%s": {
|
||||
"auth": "%s"
|
||||
}
|
||||
}
|
||||
}
|
||||
`, cfg.acr.url, b64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", cfg.acr.username, cfg.acr.password)))),
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
imageRepository := reflectorv1beta2.ImageRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &imageRepository, func() error {
|
||||
imageRepository.Spec = reflectorv1beta2.ImageRepositorySpec{
|
||||
Image: fmt.Sprintf("%s/container/podinfo", cfg.acr.url),
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: acrSecret.Name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
imagePolicy := reflectorv1beta2.ImagePolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &imagePolicy, func() error {
|
||||
imagePolicy.Spec = reflectorv1beta2.ImagePolicySpec{
|
||||
ImageRepositoryRef: meta.NamespacedObjectReference{
|
||||
Name: imageRepository.Name,
|
||||
},
|
||||
Policy: reflectorv1beta2.ImagePolicyChoice{
|
||||
SemVer: &reflectorv1beta2.SemVerPolicy{
|
||||
Range: "1.0.x",
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
imageAutomation := automationv1beta1.ImageUpdateAutomation{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "podinfo",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &imageAutomation, func() error {
|
||||
imageAutomation.Spec = automationv1beta1.ImageUpdateAutomationSpec{
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
SourceRef: automationv1beta1.CrossNamespaceSourceReference{
|
||||
Kind: "GitRepository",
|
||||
Name: name,
|
||||
},
|
||||
GitSpec: &automationv1beta1.GitSpec{
|
||||
Checkout: &automationv1beta1.GitCheckoutSpec{
|
||||
Reference: sourcev1.GitRepositoryRef{
|
||||
Branch: name,
|
||||
},
|
||||
},
|
||||
Commit: automationv1beta1.CommitSpec{
|
||||
Author: automationv1beta1.CommitUser{
|
||||
Email: "imageautomation@example.com",
|
||||
Name: "imageautomation",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for image repository to be ready
|
||||
require.Eventually(t, func() bool {
|
||||
_, repoDir, err := getRepository(repoUrl, name, false, cfg.azdoPat)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
b, err := os.ReadFile(filepath.Join(repoDir, "podinfo.yaml"))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if bytes.Contains(b, []byte(newVersion)) == false {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 120*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestKeyVaultSops(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "key-vault-sops"
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
secretYaml := `apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: "test"
|
||||
namespace: "key-vault-sops"
|
||||
stringData:
|
||||
foo: "bar"`
|
||||
|
||||
repo, tmpDir, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
err = runCommand(ctx, 5*time.Minute, tmpDir, "mkdir -p ./key-vault-sops")
|
||||
require.NoError(t, err)
|
||||
err = runCommand(ctx, 5*time.Minute, tmpDir, fmt.Sprintf("echo \"%s\" > ./key-vault-sops/secret.enc.yaml", secretYaml))
|
||||
require.NoError(t, err)
|
||||
err = runCommand(ctx, 5*time.Minute, tmpDir, fmt.Sprintf("sops --encrypt --encrypted-regex '^(data|stringData)$' --azure-kv %s --in-place ./key-vault-sops/secret.enc.yaml", cfg.sopsId))
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := os.Open(fmt.Sprintf("%s/key-vault-sops/secret.enc.yaml", tmpDir))
|
||||
require.NoError(t, err)
|
||||
|
||||
files := make(map[string]io.Reader)
|
||||
files["key-vault-sops/secret.enc.yaml"] = r
|
||||
err = commitAndPushAll(repo, files, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
source := &sourcev1.GitRepository{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, source, func() error {
|
||||
source.Spec = sourcev1.GitRepositorySpec{
|
||||
Reference: &sourcev1.GitRepositoryRef{
|
||||
Branch: name,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: "https-credentials",
|
||||
},
|
||||
URL: repoUrl,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec = kustomizev1.KustomizationSpec{
|
||||
Path: "./key-vault-sops",
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: source.Name,
|
||||
Namespace: source.Namespace,
|
||||
},
|
||||
Interval: metav1.Duration{Duration: 1 * time.Minute},
|
||||
Prune: true,
|
||||
Decryption: &kustomizev1.Decryption{
|
||||
Provider: "sops",
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
nn := types.NamespacedName{Name: "test", Namespace: name}
|
||||
secret := &corev1.Secret{}
|
||||
err = cfg.kubeClient.Get(ctx, nn, secret)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 120*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestAzureDevOpsCommitStatus(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "commit-status"
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, name)
|
||||
|
||||
c, _, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
|
||||
files := make(map[string]io.Reader)
|
||||
files["configmap.yaml"] = strings.NewReader(manifest)
|
||||
|
||||
err = commitAndPushAll(c, files, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec.HealthChecks = []meta.NamespacedObjectKindReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Name: "foobar",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, name, name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
secret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "azuredevops-token",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &secret, func() error {
|
||||
secret.StringData = map[string]string{
|
||||
"token": cfg.azdoPat,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
provider := notiv1beta3.Provider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "azuredevops",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &provider, func() error {
|
||||
provider.Spec = notiv1beta3.ProviderSpec{
|
||||
Type: "azuredevops",
|
||||
Address: repoUrl,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: "azuredevops-token",
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
alert := notiv1beta3.Alert{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "azuredevops",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &alert, func() error {
|
||||
alert.Spec = notiv1beta3.AlertSpec{
|
||||
ProviderRef: meta.LocalObjectReference{
|
||||
Name: provider.Name,
|
||||
},
|
||||
EventSources: []notiv1.CrossNamespaceObjectReference{
|
||||
{
|
||||
Kind: "Kustomization",
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
u, err := giturls.Parse(repoUrl)
|
||||
require.NoError(t, err)
|
||||
id := strings.TrimLeft(u.Path, "/")
|
||||
id = strings.TrimSuffix(id, ".git")
|
||||
comp := strings.Split(id, "/")
|
||||
orgUrl := fmt.Sprintf("%s://%s/%v", u.Scheme, u.Host, comp[0])
|
||||
project := comp[1]
|
||||
repoId := comp[3]
|
||||
|
||||
repo, err := extgogit.PlainOpen(c.Path())
|
||||
require.NoError(t, err)
|
||||
|
||||
ref, err := repo.Reference(plumbing.NewBranchReferenceName(name), false)
|
||||
require.NoError(t, err)
|
||||
|
||||
rev := ref.Hash().String()
|
||||
connection := azuredevops.NewPatConnection(orgUrl, cfg.azdoPat)
|
||||
client, err := git.NewClient(ctx, connection)
|
||||
require.NoError(t, err)
|
||||
getArgs := git.GetStatusesArgs{
|
||||
Project: &project,
|
||||
RepositoryId: &repoId,
|
||||
CommitId: &rev,
|
||||
}
|
||||
require.Eventually(t, func() bool {
|
||||
statuses, err := client.GetStatuses(ctx, getArgs)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if len(*statuses) != 1 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 500*time.Second, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestEventHubNotification(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
name := "event-hub"
|
||||
|
||||
// Start listening to eventhub with latest offset
|
||||
hub, err := eventhub.NewHubFromConnectionString(cfg.eventHubSas)
|
||||
require.NoError(t, err)
|
||||
c := make(chan string, 10)
|
||||
handler := func(ctx context.Context, event *eventhub.Event) error {
|
||||
c <- string(event.Data)
|
||||
return nil
|
||||
}
|
||||
runtimeInfo, err := hub.GetRuntimeInformation(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(runtimeInfo.PartitionIDs))
|
||||
listenerHandler, err := hub.Receive(ctx, runtimeInfo.PartitionIDs[0], handler, eventhub.ReceiveWithLatestOffset())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Setup Flux resources
|
||||
repoUrl := cfg.applicationRepository.http
|
||||
manifest := fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, name)
|
||||
|
||||
repo, repoDir, err := getRepository(repoUrl, name, true, cfg.azdoPat)
|
||||
require.NoError(t, err)
|
||||
err = addFile(repoDir, "configmap.yaml", manifest)
|
||||
files := make(map[string]io.Reader)
|
||||
files["configmap.yaml"] = strings.NewReader(manifest)
|
||||
require.NoError(t, err)
|
||||
err = commitAndPushAll(repo, files, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = setupNamespace(ctx, cfg.kubeClient, repoUrl, cfg.azdoPat, name)
|
||||
require.NoError(t, err)
|
||||
|
||||
secret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &secret, func() error {
|
||||
secret.StringData = map[string]string{
|
||||
"address": cfg.eventHubSas,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
provider := notiv1beta3.Provider{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &provider, func() error {
|
||||
provider.Spec = notiv1beta3.ProviderSpec{
|
||||
Type: "azureeventhub",
|
||||
Address: repoUrl,
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
alert := notiv1beta3.Alert{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &alert, func() error {
|
||||
alert.Spec = notiv1beta3.AlertSpec{
|
||||
ProviderRef: meta.LocalObjectReference{
|
||||
Name: provider.Name,
|
||||
},
|
||||
EventSources: []notiv1.CrossNamespaceObjectReference{
|
||||
{
|
||||
Kind: "Kustomization",
|
||||
Name: name,
|
||||
Namespace: name,
|
||||
},
|
||||
},
|
||||
Summary: "cluster: test-1",
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: name}}
|
||||
require.Eventually(t, func() bool {
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, kustomization, func() error {
|
||||
kustomization.Spec.HealthChecks = []meta.NamespacedObjectKindReference{
|
||||
{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
Name: "foobar",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
err := verifyGitAndKustomization(ctx, cfg.kubeClient, name, name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}, 60*time.Second, 5*time.Second)
|
||||
|
||||
// Wait to read even from event hub
|
||||
require.Eventually(t, func() bool {
|
||||
select {
|
||||
case eventJson := <-c:
|
||||
event := &eventv1.Event{}
|
||||
err := json.Unmarshal([]byte(eventJson), event)
|
||||
if err != nil {
|
||||
t.Logf("the received event type does not match Flux format, error: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
if event.InvolvedObject.Kind == kustomizev1.KustomizationKind &&
|
||||
strings.Contains(event.Message, "Health check passed") {
|
||||
return true
|
||||
}
|
||||
|
||||
t.Logf("event received from '%s/%s': %s",
|
||||
event.InvolvedObject.Kind, event.InvolvedObject.Name, event.Message)
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}, 60*time.Second, 1*time.Second)
|
||||
err = listenerHandler.Close(ctx)
|
||||
require.NoError(t, err)
|
||||
err = hub.Close(ctx)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TODO: Enable when source-controller supports Helm charts from OCI sources.
|
||||
/*func TestACRHelmRelease(t *testing.T) {
|
||||
ctx := context.TODO()
|
||||
|
||||
// Create namespace for test
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "acr-helm-release",
|
||||
},
|
||||
}
|
||||
err := kubeClient.Create(ctx, &namespace)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
kubeClient.Delete(ctx, &namespace)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
// Copy ACR credentials to new namespace
|
||||
acrNn := types.NamespacedName{
|
||||
Name: "acr-helm",
|
||||
Namespace: "flux-system",
|
||||
}
|
||||
acrSecret := corev1.Secret{}
|
||||
err = kubeClient.Get(ctx, acrNn, &acrSecret)
|
||||
require.NoError(t, err)
|
||||
acrSecret.ObjectMeta = metav1.ObjectMeta{
|
||||
Name: acrSecret.Name,
|
||||
Namespace: namespace.Name,
|
||||
}
|
||||
err = kubeClient.Create(ctx, &acrSecret)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create HelmRepository and wait for it to sync
|
||||
helmRepository := sourcev1.HelmRepository{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "acr",
|
||||
Namespace: namespace.Name,
|
||||
},
|
||||
Spec: sourcev1.HelmRepositorySpec{
|
||||
URL: "https://acrappsoarfish.azurecr.io/helm/podinfo",
|
||||
Interval: metav1.Duration{
|
||||
Duration: 5 * time.Minute,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: acrSecret.Name,
|
||||
},
|
||||
PassCredentials: true,
|
||||
},
|
||||
}
|
||||
err = kubeClient.Create(ctx, &helmRepository)
|
||||
require.NoError(t, err)
|
||||
}*/
|
||||
123
tests/azure/go.mod
Normal file
123
tests/azure/go.mod
Normal file
@@ -0,0 +1,123 @@
|
||||
module github.com/fluxcd/flux2/tests/azure
|
||||
|
||||
go 1.20
|
||||
|
||||
// Fix CVE-2022-28948
|
||||
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-event-hubs-go/v3 v3.6.1
|
||||
github.com/chainguard-dev/git-urls v1.0.2
|
||||
github.com/fluxcd/helm-controller/api v0.37.4
|
||||
github.com/fluxcd/image-automation-controller/api v0.37.1
|
||||
github.com/fluxcd/image-reflector-controller/api v0.31.2
|
||||
github.com/fluxcd/kustomize-controller/api v1.2.2
|
||||
github.com/fluxcd/notification-controller/api v1.2.4
|
||||
github.com/fluxcd/pkg/apis/event v0.7.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.3.0
|
||||
github.com/fluxcd/pkg/git v0.17.0
|
||||
github.com/fluxcd/pkg/git/gogit v0.17.0
|
||||
github.com/fluxcd/source-controller/api v1.2.4
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/hashicorp/hc-install v0.5.2
|
||||
github.com/hashicorp/terraform-exec v0.18.1
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.uber.org/multierr v1.11.0
|
||||
k8s.io/api v0.28.6
|
||||
k8s.io/apimachinery v0.28.6
|
||||
k8s.io/client-go v0.28.6
|
||||
k8s.io/klog/v2 v2.110.1
|
||||
sigs.k8s.io/controller-runtime v0.16.3
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.2.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible // indirect
|
||||
github.com/Azure/go-amqp v1.0.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.28 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.21 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/devigned/tab v0.1.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.1.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.3.0 // indirect
|
||||
github.com/fluxcd/pkg/ssh v0.11.0 // indirect
|
||||
github.com/fluxcd/pkg/version v0.2.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/zapr v1.3.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/uuid v1.5.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.15.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.18.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/skeema/knownhosts v1.2.1 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/zclconf/go-cty v1.13.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/term v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
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/apiextensions-apiserver v0.28.6 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8 // indirect
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
393
tests/azure/go.sum
Normal file
393
tests/azure/go.sum
Normal file
@@ -0,0 +1,393 @@
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.2.0 h1:q/jLx1KJ8xeI8XGfkOWMN9XrXzAfVTkyvCxPvHCjd2I=
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.2.0/go.mod h1:GD3m/WPPma+621UaU6KNjKEo5Hl09z86viKwQjTpV0Q=
|
||||
github.com/Azure/azure-event-hubs-go/v3 v3.6.1 h1:vSiMmn3tOwgiLyfnmhT5K6Of/3QWRLaaNZPI0hFvZyU=
|
||||
github.com/Azure/azure-event-hubs-go/v3 v3.6.1/go.mod h1:i2NByb9Pr2na7y8wi/XefEVKkuA2CDUjCNoWQJtTsGo=
|
||||
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw=
|
||||
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-amqp v1.0.0 h1:QfCugi1M+4F2JDTRgVnRw7PYXLXZ9hmqk3+9+oJh3OA=
|
||||
github.com/Azure/go-amqp v1.0.0/go.mod h1:+bg0x3ce5+Q3ahCEXnCsGG3ETpDQe3MEVnOuT2ywPwc=
|
||||
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.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM=
|
||||
github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 h1:LXl088ZQlP0SBppGFsRZonW6hSvwgL5gRByMbvUbx8U=
|
||||
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/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
|
||||
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
|
||||
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/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ=
|
||||
github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/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/devigned/tab v0.1.1 h1:3mD6Kb1mUOYeLpJvTVSDwSg5ZsfSxfvxGRTxRsJsITA=
|
||||
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
|
||||
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
|
||||
github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 h1:m62nsMU279qRD9PQSWD1l66kmkXzuYcnVJqL4XLeV2M=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
|
||||
github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
|
||||
github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
|
||||
github.com/fluxcd/helm-controller/api v0.37.4 h1:rkBMqYXexyf1s5BS8QpxGi691DsCi+yugIFCM5fNKLU=
|
||||
github.com/fluxcd/helm-controller/api v0.37.4/go.mod h1:KFdP5Lbrc4Vv+Jt4xRj6UUo3qiwdBqBPl1xiiAnBe9c=
|
||||
github.com/fluxcd/image-automation-controller/api v0.37.1 h1:zi1VfPoGuHsNtyTpueKbr4b/c+Ms7HjFocTAmixmYno=
|
||||
github.com/fluxcd/image-automation-controller/api v0.37.1/go.mod h1:7p0woxB275YzhdctzbxVMck0/hZt45bm0K12A0ABldo=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.31.2 h1:s16ewwfuLBYuh8hENuVgU8SYsSNxRaA4f+AD60/+les=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.31.2/go.mod h1:tV7g+KXQL3W8w5+fRJU7ubVGc4QAfx1C7XI5qrQvA3U=
|
||||
github.com/fluxcd/kustomize-controller/api v1.2.2 h1:LXRa2181usLsDkAJ86i/CnvCyPwhLcFUw9jBnXxTFJ4=
|
||||
github.com/fluxcd/kustomize-controller/api v1.2.2/go.mod h1:dfAaPQuuoWfExyWaeO7Kj2ZtfKQ4nDcJrt7AeAFlLZs=
|
||||
github.com/fluxcd/notification-controller/api v1.2.4 h1:H/C8XW5boncf8rzJjSe/MCr186Hgvw+arPat9XOaRlw=
|
||||
github.com/fluxcd/notification-controller/api v1.2.4/go.mod h1:LeHtKKTI3ew+FXY0oYtYqM68UYOArfBa/cy4pxAzN4M=
|
||||
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/event v0.7.0 h1:QN/gz9i5kZ3GlfTOE6SCjjnSXrSPUU75MCVRwN8U+qo=
|
||||
github.com/fluxcd/pkg/apis/event v0.7.0/go.mod h1:zdqe8SVXjFQ/Nfuk51c2SJe0NkyNwYOxSFtN6SmikVs=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.3.0 h1:qvB46CfaOWcL1SyR2RiVWN/j7/035D0OtB1ltLN7rgI=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.3.0/go.mod h1:PCXf5kktTzNav0aH2Ns3jsowqwmA9xTcsrEOoPzx/K8=
|
||||
github.com/fluxcd/pkg/apis/meta v1.3.0 h1:KxeEc6olmSZvQ5pBONPE4IKxyoWQbqTJF1X6K5nIXpU=
|
||||
github.com/fluxcd/pkg/apis/meta v1.3.0/go.mod h1:3Ui8xFkoU4sYehqmscjpq7NjqH2YN1A2iX2okbO3/yA=
|
||||
github.com/fluxcd/pkg/git v0.17.0 h1:eHL8IazeX2HXwXzT6zLdzGaX3H37n/ipkdd1+byyzUM=
|
||||
github.com/fluxcd/pkg/git v0.17.0/go.mod h1:lBeHCTtVt9py9mMGj5sKs4+aFpMWGjH73gx5i818i6o=
|
||||
github.com/fluxcd/pkg/git/gogit v0.17.0 h1:X8C+q/Nm/MjBKAoqw9NPpnJh0B3IxVLtqPgH+wT9NEg=
|
||||
github.com/fluxcd/pkg/git/gogit v0.17.0/go.mod h1:qyRSCQy41wG0FwUwKQtfSnwqkrJg5XB4UdMvrHjIcFY=
|
||||
github.com/fluxcd/pkg/gittestserver v0.10.0 h1:joqfczQNtguZFGxTuRL535ymDW/9clA1jBWa3d8B6WU=
|
||||
github.com/fluxcd/pkg/ssh v0.11.0 h1:7WDDrcB0cNimzZjrpkzYBrizkrUgyM4Zr2cd9z9aqpU=
|
||||
github.com/fluxcd/pkg/ssh v0.11.0/go.mod h1:K8YgH8KM0GV5DWuRErX3iKgpoHlYh08SBK+U5Q0teJc=
|
||||
github.com/fluxcd/pkg/version v0.2.2 h1:ZpVXECeLA5hIQMft11iLp6gN3cKcz6UNuVTQPw/bRdI=
|
||||
github.com/fluxcd/pkg/version v0.2.2/go.mod h1:NGnh/no8S6PyfCDxRFrPY3T5BUnqP48MxfxNRU0z8C0=
|
||||
github.com/fluxcd/source-controller/api v1.2.4 h1:XjKTWhSSeLGsogWnTcLl5sUnyMlC5TKDbbBgP9SyJ5c=
|
||||
github.com/fluxcd/source-controller/api v1.2.4/go.mod h1:j3QSHpIPBP5sjaGIkVtsgWCx8JcOmcsutRmdJmRMOZg=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
|
||||
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
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/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.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.1.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.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
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/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
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.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
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-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hc-install v0.5.2 h1:SfwMFnEXVVirpwkDuSF5kymUOhrUxrTq3udEseZdOD0=
|
||||
github.com/hashicorp/hc-install v0.5.2/go.mod h1:9QISwe6newMWIfEiXpzuu1k9HAGtQYgnSH8H9T8wmoI=
|
||||
github.com/hashicorp/terraform-exec v0.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4=
|
||||
github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980=
|
||||
github.com/hashicorp/terraform-json v0.15.0 h1:/gIyNtR6SFw6h5yzlbDbACyGvIhKtQi8mTsbkNd79lE=
|
||||
github.com/hashicorp/terraform-json v0.15.0/go.mod h1:+L1RNzjDU5leLFZkHTFTbJXaoqUC6TqXlFgDoOXrtvk=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 h1:YH424zrwLTlyHSH/GzLMJeu5zhYVZSx5RQxGKm1h96s=
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
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=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
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/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
|
||||
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
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.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
|
||||
github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
|
||||
github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0=
|
||||
github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
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=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
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=
|
||||
k8s.io/api v0.28.6 h1:yy6u9CuIhmg55YvF/BavPBBXB+5QicB64njJXxVnzLo=
|
||||
k8s.io/api v0.28.6/go.mod h1:AM6Ys6g9MY3dl/XNaNfg/GePI0FT7WBGu8efU/lirAo=
|
||||
k8s.io/apiextensions-apiserver v0.28.6 h1:myB3iG/3v3jqCg28JDbOefu4sH2/erNEXgytRzJKBOo=
|
||||
k8s.io/apiextensions-apiserver v0.28.6/go.mod h1:qlp6xRKBgyRhe5AYc81TQpLx4kLNK8/sGQUOwMkVjRk=
|
||||
k8s.io/apimachinery v0.28.6 h1:RsTeR4z6S07srPg6XYrwXpTJVMXsjPXn0ODakMytSW0=
|
||||
k8s.io/apimachinery v0.28.6/go.mod h1:QFNX/kCl/EMT2WTSz8k4WLCv2XnkOLMaL8GAVRMdpsA=
|
||||
k8s.io/client-go v0.28.6 h1:Gge6ziyIdafRchfoBKcpaARuz7jfrK1R1azuwORIsQI=
|
||||
k8s.io/client-go v0.28.6/go.mod h1:+nu0Yp21Oeo/cBCsprNVXB2BfJTV51lFfe5tXl2rUL8=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
||||
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8 h1:vzKzxN5uyJZLY8HL1/OovW7BJefnsBIWt8T7Gjh2boQ=
|
||||
k8s.io/kube-openapi v0.0.0-20231206194836-bf4651e18aa8/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI=
|
||||
k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4=
|
||||
sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0=
|
||||
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/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
81
tests/azure/terraform/aks/.terraform.lock.hcl
generated
Normal file
81
tests/azure/terraform/aks/.terraform.lock.hcl
generated
Normal file
@@ -0,0 +1,81 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azuread" {
|
||||
version = "2.28.0"
|
||||
constraints = "2.28.0"
|
||||
hashes = [
|
||||
"h1:22zcPLrP6T0FAGzhkx44Oc3SreGpzttng34JSYhoknE=",
|
||||
"zh:0e8b008417d74f7d7f931effe48c0719f20789440c9c5932c2b1cf4110348f41",
|
||||
"zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7",
|
||||
"zh:2a2e4408fc1dc902553ff6a5751924c5e9a59df30f0668b55aa6c07264537c03",
|
||||
"zh:2ab09b735888a7402bdd8e74f75a053ac102e0a01b876b0608a0c240dff57b2e",
|
||||
"zh:2ac1f45bb1597726ff6822e1f9a7bc7227179c10b0b51533849b44ab278a05ed",
|
||||
"zh:601a7821c7fbef870a1a2165a684e4fb4f4c84f6b85e0ce51ef7783a581cf594",
|
||||
"zh:7f8e4dd03a3d4259e06b498ed0b04c6911aa99cf5f01018e2092899cd135c6e5",
|
||||
"zh:8408143a24baaf4ad527aeecfaf11dfcd0fb6f25648958f2c94464717f776206",
|
||||
"zh:bc836c1389f7b01537eb71ec709ea9d1cb4180814b70992ce3004356ce28d173",
|
||||
"zh:d4b5571c96c2bafdf79494265f508dbe569f6fb16a5ddc41f22da22e9be029e9",
|
||||
"zh:f1c2a1a13fe3725ba84b57a418adb1bd8c93db09dd880658a468cbd4832f9224",
|
||||
"zh:f39b090d45674395fecb39add1260dd4565661e38eb40c4017c3fd84c8af1717",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azurerm" {
|
||||
version = "3.20.0"
|
||||
constraints = "3.20.0"
|
||||
hashes = [
|
||||
"h1:heH/4bYgajEFQ+fwSV9Zduvpyb7eTCQUv+gl201EFg8=",
|
||||
"zh:0d534bb2fed67b5b58d3adb2b0be7a9986f62b34f40eae450dafc9454fb54db8",
|
||||
"zh:19f6d5f196a35500e0f1ae9d9baee44f49b90858524338a7b8aaec06d3e3a047",
|
||||
"zh:1d042648d2eaffde8858a8006b944374599c5e8c2f834ae74b97adedd1468142",
|
||||
"zh:278ebac38cf3c1e6df4bc5de00e931bfc04298607f428aa84a932bbf26dee421",
|
||||
"zh:48f29b802e2de7e6dd2452a012c633686fce5d7ad3eadb490a7b8c0967a9ebfa",
|
||||
"zh:731bf2e97c4a519723682beb2e85e065bf0bf53b2f50e2ff7b15b39ea74e37ff",
|
||||
"zh:7c8187ebca19ca8f6ef82d3d79a418ccfa6574bb99e63cc930fa46ff938a7921",
|
||||
"zh:82fdb2052601f6fa925195e77506fb609ce8bb4a6f6e94cf6a5058252ef570d4",
|
||||
"zh:995ca23bb3765a16c6b3138b468d920acff5742b22492324c836579e3344ea40",
|
||||
"zh:a970131232ad41203382f6fa3f0014a22767cbfe28cd7562346184ea6e678d63",
|
||||
"zh:bf5036675a7f0b8691fe393e2782a76c7943ba17eec7255e16a31c7547436a48",
|
||||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.4.3"
|
||||
hashes = [
|
||||
"h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=",
|
||||
"zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752",
|
||||
"zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b",
|
||||
"zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3",
|
||||
"zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5",
|
||||
"zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda",
|
||||
"zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6",
|
||||
"zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1",
|
||||
"zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d",
|
||||
"zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8",
|
||||
"zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/microsoft/azuredevops" {
|
||||
version = "0.2.2"
|
||||
constraints = "0.2.2"
|
||||
hashes = [
|
||||
"h1:oKfPQ5Tp9WNeacY08gMifP3G9I//o3LW6qTLsveJwi0=",
|
||||
"zh:016142d26ec662949ba95b6c84672b243b54bbdca04cf8714fe0b4318783a72d",
|
||||
"zh:0337b3c4e023bb56b23a5d2d9abe917f197eed378fa69803e9d0b11a36211e15",
|
||||
"zh:240c9636660292eeb99bd892602eafe2e5c22b469b082de6963e31dab9e0092e",
|
||||
"zh:439151590a489a7c0cde50ee701fdbf254e67bdbeaa2acd2a99d005c4051d518",
|
||||
"zh:6086f5eab87662678eef7bc83041eab5667e92189eb3089b966aeb2cdb58d299",
|
||||
"zh:94a64223905bb3cef2c38e163ae56ef841422e6511a79f8e60272edd7f8fc67f",
|
||||
"zh:9d9545445607c5ba6482da0137464d5de4c3459ae1671e6ff94e337e5943c0eb",
|
||||
"zh:a53bfdea73985ed31acbadd200b295745662a4a54e8c37f050faf71dab7deb8b",
|
||||
"zh:aa6943db7093b2556fcc2ee5b8b5a8a48e625ded2b063183fbc5a52c94d133f2",
|
||||
"zh:af4729e8fe8ec255e4c4ca0e6dd4cf43d855bfe4c45b2aa6e47d8c35be55813d",
|
||||
"zh:bdf8752a6cd12ba3a33597bf7519825000a498b655c72be8c8df504bb9f70fe5",
|
||||
"zh:c760fa7bc5c62d56c54ef41b4b03b0ae391149f46f36c8c8a55d2511e7f8e599",
|
||||
]
|
||||
}
|
||||
35
tests/azure/terraform/aks/aks.tf
Normal file
35
tests/azure/terraform/aks/aks.tf
Normal file
@@ -0,0 +1,35 @@
|
||||
resource "azurerm_kubernetes_cluster" "this" {
|
||||
name = "aks-${local.name_suffix}"
|
||||
location = azurerm_resource_group.this.location
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
|
||||
dns_prefix = "aks${local.name_suffix}"
|
||||
|
||||
default_node_pool {
|
||||
name = "default"
|
||||
node_count = 2
|
||||
vm_size = "Standard_B2s"
|
||||
os_disk_size_gb = 30
|
||||
}
|
||||
|
||||
identity {
|
||||
type = "SystemAssigned"
|
||||
}
|
||||
|
||||
role_based_access_control_enabled = true
|
||||
|
||||
network_profile {
|
||||
network_plugin = "kubenet"
|
||||
network_policy = "calico"
|
||||
}
|
||||
|
||||
tags = {
|
||||
environment = "e2e"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "aks_acr_pull" {
|
||||
scope = data.azurerm_container_registry.shared.id
|
||||
role_definition_name = "AcrPull"
|
||||
principal_id = azurerm_kubernetes_cluster.this.kubelet_identity[0].object_id
|
||||
}
|
||||
21
tests/azure/terraform/aks/azuredevops.tf
Normal file
21
tests/azure/terraform/aks/azuredevops.tf
Normal file
@@ -0,0 +1,21 @@
|
||||
data "azuredevops_project" "e2e" {
|
||||
name = "e2e"
|
||||
}
|
||||
|
||||
resource "azuredevops_git_repository" "fleet_infra" {
|
||||
project_id = data.azuredevops_project.e2e.id
|
||||
name = "fleet-infra-${local.name_suffix}"
|
||||
default_branch = "refs/heads/main"
|
||||
initialization {
|
||||
init_type = "Clean"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuredevops_git_repository" "application" {
|
||||
project_id = data.azuredevops_project.e2e.id
|
||||
name = "application-${local.name_suffix}"
|
||||
default_branch = "refs/heads/main"
|
||||
initialization {
|
||||
init_type = "Clean"
|
||||
}
|
||||
}
|
||||
26
tests/azure/terraform/aks/event-hub.tf
Normal file
26
tests/azure/terraform/aks/event-hub.tf
Normal file
@@ -0,0 +1,26 @@
|
||||
resource "azurerm_eventhub_namespace" "this" {
|
||||
name = "ehns-${local.name_suffix}"
|
||||
location = azurerm_resource_group.this.location
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
sku = "Standard"
|
||||
capacity = 1
|
||||
}
|
||||
|
||||
|
||||
resource "azurerm_eventhub" "this" {
|
||||
name = "eh-${local.name_suffix}"
|
||||
namespace_name = azurerm_eventhub_namespace.this.name
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
partition_count = 1
|
||||
message_retention = 1
|
||||
}
|
||||
|
||||
resource "azurerm_eventhub_authorization_rule" "this" {
|
||||
name = "flux"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
namespace_name = azurerm_eventhub_namespace.this.name
|
||||
eventhub_name = azurerm_eventhub.this.name
|
||||
listen = true
|
||||
send = true
|
||||
manage = false
|
||||
}
|
||||
37
tests/azure/terraform/aks/keyvault.tf
Normal file
37
tests/azure/terraform/aks/keyvault.tf
Normal file
@@ -0,0 +1,37 @@
|
||||
resource "azurerm_key_vault" "this" {
|
||||
name = "kv-${random_pet.suffix.id}"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
location = azurerm_resource_group.this.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "sops_write" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = data.azurerm_client_config.current.object_id
|
||||
|
||||
key_permissions = [
|
||||
"Encrypt",
|
||||
"Decrypt",
|
||||
"Create",
|
||||
"Delete",
|
||||
"Purge",
|
||||
"Get",
|
||||
"List",
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_key" "sops" {
|
||||
depends_on = [azurerm_key_vault_access_policy.sops_write]
|
||||
|
||||
name = "sops"
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
key_type = "RSA"
|
||||
key_size = 2048
|
||||
|
||||
key_opts = [
|
||||
"decrypt",
|
||||
"encrypt",
|
||||
]
|
||||
}
|
||||
52
tests/azure/terraform/aks/main.tf
Normal file
52
tests/azure/terraform/aks/main.tf
Normal file
@@ -0,0 +1,52 @@
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "terraform-state"
|
||||
storage_account_name = "terraformstate0419"
|
||||
container_name = "aks-tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
}
|
||||
|
||||
required_version = "1.2.8"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "3.20.0"
|
||||
}
|
||||
azuread = {
|
||||
source = "hashicorp/azuread"
|
||||
version = "2.28.0"
|
||||
}
|
||||
azuredevops = {
|
||||
source = "microsoft/azuredevops"
|
||||
version = "0.2.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
||||
|
||||
provider "azuredevops" {
|
||||
org_service_url = "https://dev.azure.com/${local.azure_devops_org}"
|
||||
personal_access_token = data.azurerm_key_vault_secret.shared_pat.value
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
resource "random_pet" "suffix" {}
|
||||
|
||||
locals {
|
||||
azure_devops_org = "flux-azure"
|
||||
name_suffix = "e2e-${random_pet.suffix.id}"
|
||||
}
|
||||
|
||||
resource "azurerm_resource_group" "this" {
|
||||
name = "rg-${local.name_suffix}"
|
||||
location = "West Europe"
|
||||
|
||||
tags = {
|
||||
environment = "e2e"
|
||||
}
|
||||
}
|
||||
80
tests/azure/terraform/aks/outputs.tf
Normal file
80
tests/azure/terraform/aks/outputs.tf
Normal file
@@ -0,0 +1,80 @@
|
||||
output "aks_kube_config" {
|
||||
sensitive = true
|
||||
value = azurerm_kubernetes_cluster.this.kube_config_raw
|
||||
}
|
||||
|
||||
output "aks_host" {
|
||||
value = azurerm_kubernetes_cluster.this.kube_config[0].host
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "aks_client_certificate" {
|
||||
value = base64decode(azurerm_kubernetes_cluster.this.kube_config[0].client_certificate)
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "aks_client_key" {
|
||||
value = base64decode(azurerm_kubernetes_cluster.this.kube_config[0].client_key)
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "aks_cluster_ca_certificate" {
|
||||
value = base64decode(azurerm_kubernetes_cluster.this.kube_config[0].cluster_ca_certificate)
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "shared_pat" {
|
||||
sensitive = true
|
||||
value = data.azurerm_key_vault_secret.shared_pat.value
|
||||
}
|
||||
|
||||
output "shared_id_rsa" {
|
||||
sensitive = true
|
||||
value = data.azurerm_key_vault_secret.shared_id_rsa.value
|
||||
}
|
||||
|
||||
output "shared_id_rsa_pub" {
|
||||
sensitive = true
|
||||
value = data.azurerm_key_vault_secret.shared_id_rsa_pub.value
|
||||
}
|
||||
|
||||
output "fleet_infra_repository" {
|
||||
value = {
|
||||
http = azuredevops_git_repository.fleet_infra.remote_url
|
||||
ssh = "ssh://git@ssh.dev.azure.com/v3/${local.azure_devops_org}/${azuredevops_git_repository.fleet_infra.project_id}/${azuredevops_git_repository.fleet_infra.name}"
|
||||
}
|
||||
}
|
||||
|
||||
output "application_repository" {
|
||||
value = {
|
||||
http = azuredevops_git_repository.application.remote_url
|
||||
ssh = "ssh://git@ssh.dev.azure.com/v3/${local.azure_devops_org}/${azuredevops_git_repository.application.project_id}/${azuredevops_git_repository.application.name}"
|
||||
}
|
||||
}
|
||||
|
||||
output "flux_azure_sp" {
|
||||
value = {
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
client_id = azuread_service_principal.flux.application_id
|
||||
client_secret = azuread_service_principal_password.flux.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "event_hub_sas" {
|
||||
value = azurerm_eventhub_authorization_rule.this.primary_connection_string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "sops_id" {
|
||||
value = azurerm_key_vault_key.sops.id
|
||||
}
|
||||
|
||||
output "acr" {
|
||||
value = {
|
||||
url = data.azurerm_container_registry.shared.login_server
|
||||
username = azuread_service_principal.flux.application_id
|
||||
password = azuread_service_principal_password.flux.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
52
tests/azure/terraform/aks/service-principal.tf
Normal file
52
tests/azure/terraform/aks/service-principal.tf
Normal file
@@ -0,0 +1,52 @@
|
||||
resource "azuread_application" "flux" {
|
||||
display_name = "flux-${local.name_suffix}"
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000003-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "df021288-bdef-4463-88db-98f22de89214"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000002-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "1cda74f2-2616-4834-b122-5cb1b07f8a59"
|
||||
type = "Role"
|
||||
}
|
||||
resource_access {
|
||||
id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuread_service_principal" "flux" {
|
||||
application_id = azuread_application.flux.application_id
|
||||
}
|
||||
|
||||
resource "azuread_service_principal_password" "flux" {
|
||||
service_principal_id = azuread_service_principal.flux.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "acr" {
|
||||
scope = data.azurerm_container_registry.shared.id
|
||||
role_definition_name = "AcrPull"
|
||||
principal_id = azuread_service_principal.flux.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "sops_decrypt" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = azuread_service_principal.flux.object_id
|
||||
|
||||
key_permissions = [
|
||||
"Encrypt",
|
||||
"Decrypt",
|
||||
"Get",
|
||||
"List",
|
||||
]
|
||||
}
|
||||
32
tests/azure/terraform/aks/shared.tf
Normal file
32
tests/azure/terraform/aks/shared.tf
Normal file
@@ -0,0 +1,32 @@
|
||||
locals {
|
||||
shared_suffix = "oarfish"
|
||||
}
|
||||
|
||||
data "azurerm_resource_group" "shared" {
|
||||
name = "e2e-shared"
|
||||
}
|
||||
|
||||
data "azurerm_container_registry" "shared" {
|
||||
name = "acrapps${local.shared_suffix}"
|
||||
resource_group_name = data.azurerm_resource_group.shared.name
|
||||
}
|
||||
|
||||
data "azurerm_key_vault" "shared" {
|
||||
resource_group_name = data.azurerm_resource_group.shared.name
|
||||
name = "kv-credentials-${local.shared_suffix}"
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "shared_pat" {
|
||||
key_vault_id = data.azurerm_key_vault.shared.id
|
||||
name = "pat"
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "shared_id_rsa" {
|
||||
key_vault_id = data.azurerm_key_vault.shared.id
|
||||
name = "id-rsa"
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "shared_id_rsa_pub" {
|
||||
key_vault_id = data.azurerm_key_vault.shared.id
|
||||
name = "id-rsa-pub"
|
||||
}
|
||||
61
tests/azure/terraform/shared/.terraform.lock.hcl
generated
Normal file
61
tests/azure/terraform/shared/.terraform.lock.hcl
generated
Normal file
@@ -0,0 +1,61 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azuread" {
|
||||
version = "2.28.0"
|
||||
constraints = "2.28.0"
|
||||
hashes = [
|
||||
"h1:22zcPLrP6T0FAGzhkx44Oc3SreGpzttng34JSYhoknE=",
|
||||
"zh:0e8b008417d74f7d7f931effe48c0719f20789440c9c5932c2b1cf4110348f41",
|
||||
"zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7",
|
||||
"zh:2a2e4408fc1dc902553ff6a5751924c5e9a59df30f0668b55aa6c07264537c03",
|
||||
"zh:2ab09b735888a7402bdd8e74f75a053ac102e0a01b876b0608a0c240dff57b2e",
|
||||
"zh:2ac1f45bb1597726ff6822e1f9a7bc7227179c10b0b51533849b44ab278a05ed",
|
||||
"zh:601a7821c7fbef870a1a2165a684e4fb4f4c84f6b85e0ce51ef7783a581cf594",
|
||||
"zh:7f8e4dd03a3d4259e06b498ed0b04c6911aa99cf5f01018e2092899cd135c6e5",
|
||||
"zh:8408143a24baaf4ad527aeecfaf11dfcd0fb6f25648958f2c94464717f776206",
|
||||
"zh:bc836c1389f7b01537eb71ec709ea9d1cb4180814b70992ce3004356ce28d173",
|
||||
"zh:d4b5571c96c2bafdf79494265f508dbe569f6fb16a5ddc41f22da22e9be029e9",
|
||||
"zh:f1c2a1a13fe3725ba84b57a418adb1bd8c93db09dd880658a468cbd4832f9224",
|
||||
"zh:f39b090d45674395fecb39add1260dd4565661e38eb40c4017c3fd84c8af1717",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azurerm" {
|
||||
version = "3.20.0"
|
||||
constraints = "3.20.0"
|
||||
hashes = [
|
||||
"h1:heH/4bYgajEFQ+fwSV9Zduvpyb7eTCQUv+gl201EFg8=",
|
||||
"zh:0d534bb2fed67b5b58d3adb2b0be7a9986f62b34f40eae450dafc9454fb54db8",
|
||||
"zh:19f6d5f196a35500e0f1ae9d9baee44f49b90858524338a7b8aaec06d3e3a047",
|
||||
"zh:1d042648d2eaffde8858a8006b944374599c5e8c2f834ae74b97adedd1468142",
|
||||
"zh:278ebac38cf3c1e6df4bc5de00e931bfc04298607f428aa84a932bbf26dee421",
|
||||
"zh:48f29b802e2de7e6dd2452a012c633686fce5d7ad3eadb490a7b8c0967a9ebfa",
|
||||
"zh:731bf2e97c4a519723682beb2e85e065bf0bf53b2f50e2ff7b15b39ea74e37ff",
|
||||
"zh:7c8187ebca19ca8f6ef82d3d79a418ccfa6574bb99e63cc930fa46ff938a7921",
|
||||
"zh:82fdb2052601f6fa925195e77506fb609ce8bb4a6f6e94cf6a5058252ef570d4",
|
||||
"zh:995ca23bb3765a16c6b3138b468d920acff5742b22492324c836579e3344ea40",
|
||||
"zh:a970131232ad41203382f6fa3f0014a22767cbfe28cd7562346184ea6e678d63",
|
||||
"zh:bf5036675a7f0b8691fe393e2782a76c7943ba17eec7255e16a31c7547436a48",
|
||||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.3.2"
|
||||
hashes = [
|
||||
"h1:H5V+7iXol/EHB2+BUMzGlpIiCOdV74H8YjzCxnSAWcg=",
|
||||
"zh:038293aebfede983e45ee55c328e3fde82ae2e5719c9bd233c324cfacc437f9c",
|
||||
"zh:07eaeab03a723d83ac1cc218f3a59fceb7bbf301b38e89a26807d1c93c81cef8",
|
||||
"zh:427611a4ce9d856b1c73bea986d841a969e4c2799c8ac7c18798d0cc42b78d32",
|
||||
"zh:49718d2da653c06a70ba81fd055e2b99dfd52dcb86820a6aeea620df22cd3b30",
|
||||
"zh:5574828d90b19ab762604c6306337e6cd430e65868e13ef6ddb4e25ddb9ad4c0",
|
||||
"zh:7222e16f7833199dabf1bc5401c56d708ec052b2a5870988bc89ff85b68a5388",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:b1b2d7d934784d2aee98b0f8f07a8ccfc0410de63493ae2bf2222c165becf938",
|
||||
"zh:b8f85b6a20bd264fcd0814866f415f0a368d1123cd7879c8ebbf905d370babc8",
|
||||
"zh:c3813133acc02bbebddf046d9942e8ba5c35fc99191e3eb057957dafc2929912",
|
||||
"zh:e7a41dbc919d1de800689a81c240c27eec6b9395564630764ebb323ea82ac8a9",
|
||||
"zh:ee6d23208449a8eaa6c4f203e33f5176fa795b4b9ecf32903dffe6e2574732c2",
|
||||
]
|
||||
}
|
||||
6
tests/azure/terraform/shared/acr.tf
Normal file
6
tests/azure/terraform/shared/acr.tf
Normal file
@@ -0,0 +1,6 @@
|
||||
resource "azurerm_container_registry" "this" {
|
||||
name = "acrapps${random_pet.suffix.id}"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
location = azurerm_resource_group.this.location
|
||||
sku = "Standard"
|
||||
}
|
||||
43
tests/azure/terraform/shared/keyvault.tf
Normal file
43
tests/azure/terraform/shared/keyvault.tf
Normal file
@@ -0,0 +1,43 @@
|
||||
resource "azurerm_key_vault" "this" {
|
||||
name = "kv-credentials-${random_pet.suffix.id}"
|
||||
resource_group_name = azurerm_resource_group.this.name
|
||||
location = azurerm_resource_group.this.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "admin" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = data.azurerm_client_config.current.object_id
|
||||
|
||||
key_permissions = [
|
||||
"Backup",
|
||||
"Create",
|
||||
"Decrypt",
|
||||
"Delete",
|
||||
"Encrypt",
|
||||
"Get",
|
||||
"Import",
|
||||
"List",
|
||||
"Purge",
|
||||
"Recover",
|
||||
"Restore",
|
||||
"Sign",
|
||||
"UnwrapKey",
|
||||
"Update",
|
||||
"Verify",
|
||||
"WrapKey",
|
||||
]
|
||||
|
||||
secret_permissions = [
|
||||
"Backup",
|
||||
"Delete",
|
||||
"Get",
|
||||
"List",
|
||||
"Purge",
|
||||
"Recover",
|
||||
"Restore",
|
||||
"Set",
|
||||
]
|
||||
}
|
||||
39
tests/azure/terraform/shared/main.tf
Normal file
39
tests/azure/terraform/shared/main.tf
Normal file
@@ -0,0 +1,39 @@
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "terraform-state"
|
||||
storage_account_name = "terraformstate0419"
|
||||
container_name = "shared-tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
}
|
||||
|
||||
required_version = "1.2.8"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "3.20.0"
|
||||
}
|
||||
azuread = {
|
||||
source = "hashicorp/azuread"
|
||||
version = "2.28.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
||||
|
||||
resource "random_pet" "suffix" {
|
||||
length = 1
|
||||
separator = ""
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
data "azurerm_subscription" "current" {}
|
||||
|
||||
resource "azurerm_resource_group" "this" {
|
||||
name = "e2e-shared"
|
||||
location = "West Europe"
|
||||
}
|
||||
18
tests/azure/terraform/shared/outputs.tf
Normal file
18
tests/azure/terraform/shared/outputs.tf
Normal file
@@ -0,0 +1,18 @@
|
||||
output "azure_devops_sp" {
|
||||
value = {
|
||||
client_id = azuread_service_principal.azure_devops.application_id
|
||||
client_secret = azuread_application_password.azure_devops.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "github_sp" {
|
||||
value = {
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
subscription_id = data.azurerm_client_config.current.subscription_id
|
||||
client_id = azuread_service_principal.github.application_id
|
||||
client_secret = azuread_application_password.github.value
|
||||
}
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
105
tests/azure/terraform/shared/service-principal.tf
Normal file
105
tests/azure/terraform/shared/service-principal.tf
Normal file
@@ -0,0 +1,105 @@
|
||||
# Service Principal used by Azure DevOps to push OCI and Helm Charts
|
||||
resource "azuread_application" "azure_devops" {
|
||||
display_name = "azure-devops-${random_pet.suffix.id}"
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000003-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "df021288-bdef-4463-88db-98f22de89214"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000002-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "1cda74f2-2616-4834-b122-5cb1b07f8a59"
|
||||
type = "Role"
|
||||
}
|
||||
resource_access {
|
||||
id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuread_application_password" "azure_devops" {
|
||||
display_name = "password"
|
||||
application_object_id = azuread_application.azure_devops.object_id
|
||||
}
|
||||
|
||||
resource "azuread_service_principal" "azure_devops" {
|
||||
application_id = azuread_application.azure_devops.application_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "azure_devops_acr" {
|
||||
scope = azurerm_container_registry.this.id
|
||||
role_definition_name = "Contributor"
|
||||
principal_id = azuread_service_principal.azure_devops.object_id
|
||||
}
|
||||
|
||||
# Service Principal that is used to run the tests in GitHub Actions
|
||||
resource "azuread_application" "github" {
|
||||
display_name = "github-${random_pet.suffix.id}"
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000003-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "df021288-bdef-4463-88db-98f22de89214"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
|
||||
required_resource_access {
|
||||
resource_app_id = "00000002-0000-0000-c000-000000000000"
|
||||
|
||||
resource_access {
|
||||
id = "1cda74f2-2616-4834-b122-5cb1b07f8a59"
|
||||
type = "Role"
|
||||
}
|
||||
resource_access {
|
||||
id = "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175"
|
||||
type = "Role"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azuread_application_password" "github" {
|
||||
display_name = "password"
|
||||
application_object_id = azuread_application.github.object_id
|
||||
}
|
||||
|
||||
resource "azuread_service_principal" "github" {
|
||||
application_id = azuread_application.github.application_id
|
||||
}
|
||||
|
||||
data "azurerm_storage_account" "terraform_state" {
|
||||
resource_group_name = "terraform-state"
|
||||
name = "terraformstate0419"
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "github_resource_group" {
|
||||
scope = data.azurerm_subscription.current.id
|
||||
role_definition_name = "Contributor"
|
||||
principal_id = azuread_service_principal.github.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "github_acr" {
|
||||
scope = azurerm_container_registry.this.id
|
||||
role_definition_name = "Owner"
|
||||
principal_id = azuread_service_principal.github.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "github_keyvault_secret_read" {
|
||||
key_vault_id = azurerm_key_vault.this.id
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
object_id = azuread_service_principal.github.object_id
|
||||
|
||||
secret_permissions = [
|
||||
"Get",
|
||||
"List",
|
||||
]
|
||||
}
|
||||
0
tests/azure/terraform/shared/variables.tf
Normal file
0
tests/azure/terraform/shared/variables.tf
Normal file
457
tests/azure/util_test.go
Normal file
457
tests/azure/util_test.go
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
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 test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
helmv2beta1 "github.com/fluxcd/helm-controller/api/v2beta2"
|
||||
automationv1beta1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
reflectorv1beta2 "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
||||
notiv1 "github.com/fluxcd/notification-controller/api/v1"
|
||||
notiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
"github.com/fluxcd/pkg/git"
|
||||
"github.com/fluxcd/pkg/git/gogit"
|
||||
"github.com/fluxcd/pkg/git/repository"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
extgogit "github.com/go-git/go-git/v5"
|
||||
gitconfig "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/http"
|
||||
)
|
||||
|
||||
const defaultBranch = "main"
|
||||
|
||||
// getKubernetesCredentials returns a path to a kubeconfig file and a kube client instance.
|
||||
func getKubernetesCredentials(kubeconfig, aksHost, aksCert, aksKey, aksCa string) (string, client.Client, error) {
|
||||
tmpDir, err := os.MkdirTemp("", "*-azure-e2e")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
kubeconfigPath := fmt.Sprintf("%s/kubeconfig", tmpDir)
|
||||
os.WriteFile(kubeconfigPath, []byte(kubeconfig), 0750)
|
||||
kubeCfg := &rest.Config{
|
||||
Host: aksHost,
|
||||
TLSClientConfig: rest.TLSClientConfig{
|
||||
CertData: []byte(aksCert),
|
||||
KeyData: []byte(aksKey),
|
||||
CAData: []byte(aksCa),
|
||||
},
|
||||
}
|
||||
err = sourcev1b2.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = sourcev1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = kustomizev1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = helmv2beta1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = reflectorv1beta2.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = automationv1beta1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = notiv1beta3.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
err = notiv1.AddToScheme(scheme.Scheme)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
kubeClient, err := client.New(kubeCfg, client.Options{Scheme: scheme.Scheme})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
return kubeconfigPath, kubeClient, nil
|
||||
}
|
||||
|
||||
// installFlux adds the core Flux components to the cluster specified in the kubeconfig file.
|
||||
func installFlux(ctx context.Context, kubeClient client.Client, kubeconfigPath, repoUrl, azdoPat string, sp spConfig) error {
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "flux-system",
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, cfg.kubeClient, &namespace, func() error {
|
||||
return nil
|
||||
})
|
||||
|
||||
azureSp := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "azure-sp", Namespace: "flux-system"}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, azureSp, func() error {
|
||||
azureSp.StringData = map[string]string{
|
||||
"AZURE_TENANT_ID": sp.tenantId,
|
||||
"AZURE_CLIENT_ID": sp.clientId,
|
||||
"AZURE_CLIENT_SECRET": sp.clientSecret,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//// Install Flux and push files to git repository
|
||||
repo, _, err := getRepository(repoUrl, defaultBranch, true, azdoPat)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error cloning repositoriy: %w", err)
|
||||
}
|
||||
|
||||
kustomizeYaml := `
|
||||
resources:
|
||||
- gotk-components.yaml
|
||||
- gotk-sync.yaml
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kustomize-controller
|
||||
namespace: flux-system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: azure-sp
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: source-controller
|
||||
namespace: flux-system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: azure-sp
|
||||
`
|
||||
|
||||
files := make(map[string]io.Reader)
|
||||
files["clusters/e2e/flux-system/kustomization.yaml"] = strings.NewReader(kustomizeYaml)
|
||||
files["clusters/e2e/flux-system/gotk-components.yaml"] = strings.NewReader("")
|
||||
files["clusters/e2e/flux-system/gotk-sync.yaml"] = strings.NewReader("")
|
||||
err = commitAndPushAll(repo, files, defaultBranch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error committing and pushing manifests: %w", err)
|
||||
}
|
||||
|
||||
bootstrapCmd := fmt.Sprintf("flux bootstrap git --url=%s --password=%s --kubeconfig=%s"+
|
||||
" --token-auth --path=clusters/e2e --components-extra image-reflector-controller,image-automation-controller",
|
||||
repoUrl, azdoPat, kubeconfigPath)
|
||||
if err := runCommand(context.Background(), 10*time.Minute, "./", bootstrapCmd); err != nil {
|
||||
return fmt.Errorf("error running bootstrap: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCommand(ctx context.Context, timeout time.Duration, dir, command string) error {
|
||||
timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(timeoutCtx, "bash", "-c", command)
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failure to run command %s: %v", string(output), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyGitAndKustomization checks that the gitrespository and kustomization combination are working properly.
|
||||
func verifyGitAndKustomization(ctx context.Context, kubeClient client.Client, namespace, name string) error {
|
||||
nn := types.NamespacedName{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
}
|
||||
source := &sourcev1.GitRepository{}
|
||||
err := kubeClient.Get(ctx, nn, source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apimeta.IsStatusConditionPresentAndEqual(source.Status.Conditions, meta.ReadyCondition, metav1.ConditionTrue) == false {
|
||||
return fmt.Errorf("source condition not ready")
|
||||
}
|
||||
kustomization := &kustomizev1.Kustomization{}
|
||||
err = kubeClient.Get(ctx, nn, kustomization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if apimeta.IsStatusConditionPresentAndEqual(kustomization.Status.Conditions, meta.ReadyCondition, metav1.ConditionTrue) == false {
|
||||
return fmt.Errorf("kustomization condition not ready")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupNamespace(ctx context.Context, kubeClient client.Client, repoUrl, password, name string) error {
|
||||
namespace := corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(ctx, kubeClient, &namespace, func() error {
|
||||
return nil
|
||||
})
|
||||
secret := corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "https-credentials",
|
||||
Namespace: name,
|
||||
},
|
||||
}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, &secret, func() error {
|
||||
secret.StringData = map[string]string{
|
||||
"username": "git",
|
||||
"password": password,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
source := &sourcev1.GitRepository{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, source, func() error {
|
||||
source.Spec = sourcev1.GitRepositorySpec{
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
Reference: &sourcev1.GitRepositoryRef{
|
||||
Branch: name,
|
||||
},
|
||||
SecretRef: &meta.LocalObjectReference{
|
||||
Name: "https-credentials",
|
||||
},
|
||||
URL: repoUrl,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kustomization := &kustomizev1.Kustomization{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace.Name}}
|
||||
_, err = controllerutil.CreateOrUpdate(ctx, kubeClient, kustomization, func() error {
|
||||
kustomization.Spec = kustomizev1.KustomizationSpec{
|
||||
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
||||
Kind: sourcev1.GitRepositoryKind,
|
||||
Name: source.Name,
|
||||
Namespace: source.Namespace,
|
||||
},
|
||||
Interval: metav1.Duration{
|
||||
Duration: 1 * time.Minute,
|
||||
},
|
||||
Prune: true,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRepository(repoURL, branchName string, overrideBranch bool, password string) (*gogit.Client, string, error) {
|
||||
checkoutBranch := defaultBranch
|
||||
if overrideBranch == false {
|
||||
checkoutBranch = branchName
|
||||
}
|
||||
|
||||
tmpDir, err := os.MkdirTemp("", "*-repository")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
c, err := gogit.NewClient(tmpDir, &git.AuthOptions{
|
||||
Transport: git.HTTPS,
|
||||
Username: "git",
|
||||
Password: password,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
_, err = c.Clone(context.Background(), repoURL, repository.CloneConfig{
|
||||
CheckoutStrategy: repository.CheckoutStrategy{
|
||||
Branch: checkoutBranch,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
err = c.SwitchBranch(context.Background(), branchName)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return c, tmpDir, nil
|
||||
}
|
||||
|
||||
func addFile(dir, path, content string) error {
|
||||
err := os.WriteFile(filepath.Join(dir, path), []byte(content), 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func commitAndPushAll(client *gogit.Client, files map[string]io.Reader, branchName string) error {
|
||||
repo, err := extgogit.PlainOpen(client.Path())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wt, err := repo.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = wt.Checkout(&extgogit.CheckoutOptions{
|
||||
Branch: plumbing.NewBranchReferenceName(branchName),
|
||||
Force: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f := repository.WithFiles(files)
|
||||
_, err = client.Commit(git.Commit{
|
||||
Author: git.Signature{
|
||||
Name: "git",
|
||||
Email: "test@example.com",
|
||||
When: time.Now(),
|
||||
},
|
||||
Message: "add file",
|
||||
}, f)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.Push(context.Background(), repository.PushConfig{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createTagAndPush(client *gogit.Client, branchName, newTag, password string) error {
|
||||
repo, err := extgogit.PlainOpen(client.Path())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ref, err := repo.Reference(plumbing.NewBranchReferenceName(branchName), false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags, err := repo.TagObjects()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tags.ForEach(func(tag *object.Tag) error {
|
||||
if tag.Name == newTag {
|
||||
err = repo.DeleteTag(tag.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sig := &object.Signature{
|
||||
Name: "git",
|
||||
Email: "test@example.com",
|
||||
When: time.Now(),
|
||||
}
|
||||
|
||||
_, err = repo.CreateTag(newTag, ref.Hash(), &extgogit.CreateTagOptions{
|
||||
Tagger: sig,
|
||||
Message: "create tag",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
auth := &http.BasicAuth{
|
||||
Username: "git",
|
||||
Password: password,
|
||||
}
|
||||
|
||||
po := &extgogit.PushOptions{
|
||||
RemoteName: "origin",
|
||||
Progress: os.Stdout,
|
||||
RefSpecs: []gitconfig.RefSpec{gitconfig.RefSpec("refs/tags/*:refs/tags/*")},
|
||||
Auth: auth,
|
||||
}
|
||||
if err := repo.Push(po); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTestManifest(namespace string) string {
|
||||
return fmt.Sprintf(`
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: %s
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foobar
|
||||
namespace: %s
|
||||
`, namespace, namespace)
|
||||
}
|
||||
@@ -17,6 +17,14 @@ test-azure:
|
||||
test-gcp:
|
||||
$(MAKE) test PROVIDER_ARG="-provider gcp"
|
||||
|
||||
destroy:
|
||||
go test -timeout $(TEST_TIMEOUT) -v ./ $(GO_TEST_ARGS) $(PROVIDER_ARG) -destroy-only
|
||||
|
||||
destroy-azure:
|
||||
$(MAKE) destroy PROVIDER_ARG="-provider azure"
|
||||
|
||||
destroy-gcp:
|
||||
$(MAKE) destroy PROVIDER_ARG="-provider gcp"
|
||||
|
||||
sops-check:
|
||||
ifeq ($(shell which sops),)
|
||||
|
||||
@@ -74,6 +74,10 @@ variables using
|
||||
use the terraform configuration below. Please make sure all the requirements of
|
||||
azure-gh-actions are followed before running it.
|
||||
|
||||
**NOTE:** When running the following for a repo under an organization, set the
|
||||
environment variable `GITHUB_ORGANIZATION` if setting the `owner` in the
|
||||
`github` provider doesn't work.
|
||||
|
||||
```hcl
|
||||
provider "github" {
|
||||
owner = "fluxcd"
|
||||
@@ -218,7 +222,7 @@ variables using
|
||||
use the terraform configuration below. Please make sure all the requirements of
|
||||
gcp-gh-actions are followed before running it.
|
||||
|
||||
**NOTE:** When running the following for a repo under and organization, set the
|
||||
**NOTE:** When running the following for a repo under an organization, set the
|
||||
environment variable `GITHUB_ORGANIZATION` if setting the `owner` in the
|
||||
`github` provider doesn't work.
|
||||
|
||||
@@ -345,8 +349,13 @@ We also pull two version of `ghcr.io/stefanprodan/podinfo` image. These images a
|
||||
Container Registry and used to test `ImageRepository` and `ImageUpdateAutomation`. The terraform resources get created
|
||||
and the tests are run.
|
||||
|
||||
**IMPORTANT:** In case the terraform infrastructure results in a bad state, maybe due to a crash during the apply,
|
||||
the whole infrastructure can be destroyed by running terraform destroy in terraform/<provider> directory.
|
||||
If not configured explicitly to retain the infrastructure, at the end of the
|
||||
test, the test infrastructure is deleted. In case of any failure due to which
|
||||
the resources don't get deleted, the `make destroy-*` commands can be run for
|
||||
the respective provider. This will run terraform destroy in the respective
|
||||
provider's terraform configuration directory. This can be used to quickly
|
||||
destroy the infrastructure without going through the provision-test-destroy
|
||||
steps.
|
||||
|
||||
### Debugging the tests
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ require (
|
||||
github.com/fluxcd/test-infra/tftestenv v0.0.0-20240108135005-b58e0c4e0cfa
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/google/go-containerregistry v0.19.0
|
||||
github.com/hashicorp/terraform-exec v0.18.1
|
||||
github.com/hashicorp/terraform-json v0.16.0
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
|
||||
github.com/onsi/gomega v1.31.1
|
||||
@@ -89,7 +90,6 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.5.0 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.18.1 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform-exec/tfexec"
|
||||
tfjson "github.com/hashicorp/terraform-json"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
@@ -197,6 +198,20 @@ func TestMain(m *testing.M) {
|
||||
log.Fatalf("Failed to get provider config for %q", infraOpts.Provider)
|
||||
}
|
||||
|
||||
// Run destroy-only mode if enabled.
|
||||
if infraOpts.DestroyOnly {
|
||||
log.Println("Running in destroy-only mode...")
|
||||
envOpts := []tftestenv.EnvironmentOption{
|
||||
tftestenv.WithVerbose(infraOpts.Verbose),
|
||||
// Ignore any state lock in destroy-only mode.
|
||||
tftestenv.WithTfDestroyOptions(tfexec.Lock(false)),
|
||||
}
|
||||
if err := tftestenv.Destroy(ctx, providerCfg.terraformPath, envOpts...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Initialize with non-zero exit code to indicate failure by default unless
|
||||
// set by a successful test run.
|
||||
exitCode := 1
|
||||
|
||||
Reference in New Issue
Block a user