Compare commits

...

71 Commits

Author SHA1 Message Date
Juan Rodriguez
3d2e0b428b feat: add disableTls option for webhooks request
Signed-off-by: Juan Rodriguez <engineer.jrg@gmail.com>
2024-11-21 19:11:20 +05:30
Sanskar Jaiswal
7cd14761d5 Merge pull request #1713 from mingjie-li/main
Gateway API: Sort header filters to avoid canary restarts
2024-11-21 19:06:21 +05:30
Mingjie Li
b88e080a66 add test back and use slices.SortFunc
Signed-off-by: Mingjie Li <mli@liveperson.com>
2024-10-26 16:50:51 +02:00
Mingjie Li
9941843385 fix #1712 : sort gateway api header fileter to fix canary restart
Signed-off-by: Mingjie Li <mli@liveperson.com>
2024-10-26 16:50:51 +02:00
Stefan Prodan
a159421290 Merge pull request #1711 from fluxcd/update-codeowners
add @aryan9600 to CODEOWNERS
2024-10-07 23:49:57 +03:00
Sanskar Jaiswal
43cb4bc8e9 add @aryan9600 to CODEOWNERS
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-10-08 00:47:33 +05:30
Sanskar Jaiswal
b6ac5e19aa Merge pull request #1691 from fluxcd/release-v1.38.0
Release v1.38.0
2024-07-30 19:00:43 +05:30
Sanskar Jaiswal
6a090bca51 Release v1.38.0
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-07-30 13:06:44 +05:30
Stefan Prodan
e07a2618c2 Merge pull request #1676 from defenestration/add-podMonitor.honorLabels
Helm - Add podMonitor.honor labels
2024-07-29 12:50:11 +03:00
Stefan Prodan
9fcb6e9c93 Merge pull request #1690 from fluxcd/loadtester-0.33.0
Release loadtester 0.33.0
2024-07-29 12:48:47 +03:00
Stefan Prodan
a88e06db17 Release loadtester v0.33.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-07-29 12:12:00 +03:00
Stefan Prodan
401d0490da Update Kubernetes to v1.30.3
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-07-29 12:11:29 +03:00
Sanskar Jaiswal
3d1aedeb44 Merge pull request #1683 from fluxcd/fix-kuma
kuma: bump e2e version to 2.7.5
2024-07-26 15:51:33 +05:30
Sanskar Jaiswal
4015103815 kuma: disable daemonset for e2e
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-07-26 15:27:48 +05:30
Sanskar Jaiswal
74b98dab00 kuma: add ingress annotaions as custom metadata
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-07-26 15:27:47 +05:30
Sanskar Jaiswal
01dfa06891 kuma: update default namespace to kong-mesh-system
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-07-26 15:27:47 +05:30
Sanskar Jaiswal
90054b3b27 kuma: bump e2e version to 2.7.5
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-07-26 15:27:46 +05:30
Sanskar Jaiswal
cff2032ac0 Merge pull request #1686 from driv/fix_nginx_query
Fix Nginx request-duration query
2024-07-26 15:27:24 +05:30
Federico Nafria
2d5e289142 Fix Nginx request-duration query
`nginx_ingress_controller_ingress_upstream_latency_seconds_sum` measures the connection latency, not the time it takes the backend to respond.

Fixes #1685

Signed-off-by: Federico Nafria <federiconafria@gmail.com>
2024-07-19 17:08:02 +00:00
Sanskar Jaiswal
f38183bfd1 Merge pull request #1675 from fluxcd/dependabot/go_modules/google.golang.org/grpc-1.64.1
Bump google.golang.org/grpc from 1.64.0 to 1.64.1
2024-07-17 15:07:26 +05:30
Alan B
c09a61a198 add podMonitor.honorLabel
Signed-off-by: Alan B <961130+defenestration@users.noreply.github.com>
2024-07-10 10:53:58 -04:00
Alan B
417f035afb Update values.yaml
add honorLabels to default values.yaml

Signed-off-by: Alan B <961130+defenestration@users.noreply.github.com>
2024-07-10 10:51:48 -04:00
Alan B
28f2ab7bdb add honorLabels to PodMonitor
Signed-off-by: Alan B <961130+defenestration@users.noreply.github.com>
2024-07-10 10:26:54 -04:00
dependabot[bot]
d6433a16b5 Bump google.golang.org/grpc from 1.64.0 to 1.64.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.64.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.64.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-09 21:51:38 +00:00
Sanskar Jaiswal
9b39cf16f1 Merge pull request #1666 from olivierlemasle/doc/keda
doc: fix KEDA doc regarding namespaces
2024-07-01 17:17:26 +05:30
Olivier Lemasle
d2cfcbde1a doc: fix KEDA doc regarding namespaces
Fix KEDA tutorial regarding namespaces

Signed-off-by: Olivier Lemasle <olivier.lemasle@apalia.net>
2024-06-24 15:47:37 +02:00
Sanskar Jaiswal
133fdecf56 Merge pull request #1657 from shivamnarula/fix/empty-annotations-and-volumes
Fix removal of empty keys from flagger chart
2024-06-12 13:19:35 +05:30
Shivam Narula
3490d60e89 Fix removal of empty keys from flagger chart
Signed-off-by: Shivam Narula <shivamnarula@sharechat.co>
2024-06-12 12:49:35 +05:30
Sanskar Jaiswal
97d1ef0f18 Merge pull request #1630 from bacherfl/poc/keptn-provider
feat: implement a Keptn metrics provider
2024-06-12 12:31:49 +05:30
Florian Bacher
ce976e28f0 feat: implement a Keptn metrics provider
Add a Keptn metrics provider for two resources:
* KeptnMetric: Verify the value of a single metric.
* Analysis (via AnalysisDefinition): Run a Keptn analysis over an
  interval validating SLOs.

Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
2024-06-11 19:23:03 +05:30
Sanskar Jaiswal
adc60596f5 Merge pull request #1656 from fluxcd/update-deps
Update Go dependencies and Alpine
2024-05-30 23:09:04 +05:30
Sanskar Jaiswal
cf04e28774 Update Alpine to 3.20
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-05-30 21:55:44 +05:30
Sanskar Jaiswal
ba29384dd4 Update Go dependencies
Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
2024-05-30 21:55:42 +05:30
Sanskar Jaiswal
86a4514932 Merge pull request #1653 from pazmd/bump-deps-golang.org/x/net-v0.25.0
Bump golang.org/x/net to v0.25.0 and other deps.
2024-05-30 21:34:35 +05:30
pazmd
61d81ff35a Tidy dependencies.
Signed-off-by: pazmd <171067554+pazmd@users.noreply.github.com>
2024-05-29 09:50:52 +01:00
pazmd
588f91ab7b Bump golang.org/x/net to v0.25.0.
Signed-off-by: pazmd <171067554+pazmd@users.noreply.github.com>
2024-05-29 09:50:52 +01:00
Stefan Prodan
24b968029e Merge pull request #1649 from sm43/sa-annotation-support
loadtester: add support for annotation on service account
2024-05-24 18:44:29 +03:00
Shivam Mukhade
0ab3c07017 loadtester: add support for annotation on service account
this adds support to add annotation on serviceaccount when rbac is enabled.

Signed-off-by: Shivam Mukhade <shivam.mukhade@wooga.net>
2024-05-24 16:00:06 +02:00
Stefan Prodan
2d89870b14 Merge pull request #1648 from fluxcd/dependabot/github_actions/ci-610874c938
build(deps): bump the ci group across 1 directory with 2 updates
2024-05-23 10:24:47 +03:00
Sanskar Jaiswal
8e86366484 Merge pull request #1637 from ta924/matrixpanic
block panic when prom returns range vector
2024-05-23 10:21:54 +05:30
Tanner Altares
e5dfbf4adc Signed-off-by: Tanner Altares <ta924@yahoo.com>
block panic when prom returns range vector
2024-05-22 18:51:04 +05:30
Sanskar Jaiswal
04f5c68a83 Merge pull request #1634 from relu/patch-deployment-fix
Use `Patch` instead of `Update` for Deployment scaling
2024-05-22 18:32:24 +05:30
dependabot[bot]
52293a35ad ---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
- dependency-name: slsa-framework/slsa-github-generator
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-22 11:48:16 +00:00
Aurel Canciu
553184b82b Use Patch instead of Update in the deployment_controller when scaling
This should avoid frequent "Operation cannot be fulfilled" errors from
polluting Canary resource events and logs.

Signed-off-by: Aurel Canciu <aurel.canciu@nexhealth.com>
2024-05-22 17:16:16 +05:30
Sanskar Jaiswal
6289f8e371 Merge pull request #1638 from relu/k8s-1.30
Update dependencies to Kubernetes 1.30
2024-05-22 17:15:56 +05:30
Aurel Canciu
5e6815d531 Update e2e kind-related versions
Signed-off-by: Aurel Canciu <aurel.canciu@nexhealth.com>
2024-05-15 10:05:19 +03:00
Aurel Canciu
66d69f3d22 Update dependencies to Kubernetes 1.30
Signed-off-by: Aurel Canciu <aurel.canciu@nexhealth.com>
2024-05-02 12:52:01 +02:00
Stefan Prodan
9a0c6e7e54 Merge pull request #1628 from cyc0l4b/main
Bumps golang.org/x/net to v0.23.0
2024-04-12 09:50:12 +03:00
cyc0l4b
2ddbaf3324 chore: bumps golang.org/x/net to v0.23.0
Signed-off-by: cyc0l4b <cyc0l4b@proton.me>
2024-04-11 15:41:15 -03:00
Stefan Prodan
ab68d18230 Merge pull request #1624 from fluxcd/fix-release-workflow
Setup Go toolchain for release workflow
2024-03-26 15:11:52 +02:00
Stefan Prodan
214022ce7b Setup Go toolchain for release workflow
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-03-26 15:11:25 +02:00
Stefan Prodan
9acc70efc3 Merge pull request #1623 from fluxcd/release-1.37.0
Release 1.37.0
2024-03-26 14:20:43 +02:00
Stefan Prodan
4a12fc8499 Release v1.37.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-03-26 12:47:51 +02:00
Stefan Prodan
407e28e632 Release loadtester v0.32.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-03-26 12:27:11 +02:00
Stefan Prodan
82589a525d Merge pull request #1622 from fluxcd/go-1.22
Update dependencies (Go 1.22)
2024-03-26 11:38:44 +02:00
Stefan Prodan
6651751fbe Update dependencies (Go 1.22)
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2024-03-26 11:02:19 +02:00
Stefan Prodan
62fd5d2f77 Merge pull request #1620 from fluxcd/dependabot/github_actions/ci-ce785973a7
build(deps): bump the ci group with 1 update
2024-03-26 10:33:22 +02:00
Stefan Prodan
0a616df01e Merge pull request #1602 from benoitg31/main
Migrate istio VirtualService/DestinationRule to APIversion v1beta1 (current v1alpha3)
2024-03-26 10:26:30 +02:00
Stefan Prodan
f3be47d90b Merge pull request #1621 from hernit/main
Add omitempty to statuses to allow better marshalling
2024-03-26 00:59:11 +02:00
Henry Tam
935d6f9746 Add omitempty to statuses to allow better marshalling.
Signed-off-by: Henry Tam <Henry.Tam@anz.com>
2024-03-25 23:17:22 +11:00
dependabot[bot]
ded722fb2d build(deps): bump the ci group with 1 update
Bumps the ci group with 1 update: [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator).


Updates `slsa-framework/slsa-github-generator` from 1.9.0 to 1.10.0
- [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases)
- [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: slsa-framework/slsa-github-generator
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-25 11:40:20 +00:00
Stefan Prodan
a437af030a Merge pull request #1617 from sopida-chotwanwirach/gloo-reconcile-upstream-spec-change
fix(gloo): Update reconciler to detect change in gloo upstream spec
2024-03-25 09:45:12 +02:00
sopida-chotwanwirach
e3a529e1c8 switch to use patch
Signed-off-by: sopida-chotwanwirach <sopida.chotwanwirach@offerup.com>
2024-03-18 19:37:08 -07:00
sopida-chotwanwirach
e153b8a3df fix(gloo): Update reconciler to detect change in gloo upstream spec
Signed-off-by: sopida-chotwanwirach <sopida.chotwanwirach@offerup.com>
2024-03-14 14:13:02 -07:00
Stefan Prodan
c45be96f73 Merge pull request #1614 from cyc0l4b/main
Updates google.golang.org/protobuf to v1.33.0
2024-03-14 11:22:20 +02:00
cyc0l4b
dfa403705d chore: bumps google.golang.org/protobuf to v1.33
Signed-off-by: cyc0l4b <cyc0l4b@proton.me>
2024-03-12 16:40:19 -03:00
Stefan Prodan
9a0f01079f Merge pull request #1611 from LiZhenCheng9527/fix-metricTemplate
Fixed bug where query with no metric template returned an error
2024-03-07 12:03:38 +02:00
LiZhenCheng9527
b778013e07 Fixed issue where query with no metric template returned an error
Signed-off-by: LiZhenCheng9527 <lizhencheng6@huawei.com>
2024-03-07 16:06:23 +08:00
Stefan Prodan
29576900df Merge pull request #1610 from andrew-demb/patch-2
Fix link to alerting docs in changelog
2024-03-07 09:45:57 +02:00
Andrii Dembitskyi
5c70efb124 Fix link to alerting docs in changelog
Signed-off-by: Andrii Dembitskyi <andrew.dembitskiy@gmail.com>
2024-03-06 18:23:33 +02:00
Benoit Gaillard
217db66a5e make flagger use apiversion v1beta1 for istio VirtualService and DestinationRule instead of v1alpha1
Signed-off-by: Benoit Gaillard <benoit.gaillard@continental-corporation.com>
2024-02-28 15:09:40 +01:00
105 changed files with 1830 additions and 725 deletions

2
.github/CODEOWNERS vendored
View File

@@ -1 +1 @@
* @stefanprodan
* @stefanprodan @aryan9600

View File

@@ -16,13 +16,14 @@ jobs:
build-flagger:
runs-on:
group: "Default Larger Runners"
labels: ubuntu-latest-16-cores
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.21.x
go-version: 1.22.x
cache-dependency-path: |
**/go.sum
**/go.mod
@@ -31,7 +32,7 @@ jobs:
go mod download
go install golang.org/x/tools/cmd/goimports
- name: Run linters
run: make test-fmt test-codegen
run: make fmt test-codegen
- name: Verify CRDs
run: make verify-crd
- name: Run tests

View File

@@ -16,6 +16,7 @@ jobs:
e2e-test:
runs-on:
group: "Default Larger Runners"
labels: ubuntu-latest-16-cores
strategy:
fail-fast: false
matrix:
@@ -38,17 +39,17 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Kubernetes
uses: helm/kind-action@v1.9.0
uses: helm/kind-action@v1.10.0
if: matrix.provider != 'skipper'
with:
version: v0.20.0
version: v0.23.0
cluster_name: kind
node_image: kindest/node:v1.27.3@sha256:9dd3392d79af1b084671b05bcf65b21de476256ad1dcc853d9f3b10b4ac52dde
node_image: kindest/node:v1.30.0@sha256:047357ac0cfea04663786a612ba1eaba9702bef25227a794b52890dd8bcd692e
- name: Setup Kubernetes for skipper
uses: helm/kind-action@v1.9.0
uses: helm/kind-action@v1.10.0
if: matrix.provider == 'skipper'
with:
version: v0.20.0
version: v0.23.0
cluster_name: kind
node_image: kindest/node:v1.24.12@sha256:0bdca26bd7fe65c823640b14253ea7bac4baad9336b332c94850f84d8102f873
- name: Build container image

View File

@@ -17,7 +17,7 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- uses: sigstore/cosign-installer@v3.4.0
- uses: sigstore/cosign-installer@v3.5.0
- name: Prepare
id: prep
run: |

View File

@@ -28,8 +28,12 @@ jobs:
packages: write # needed for ghcr access
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x
- uses: fluxcd/flux2/action@main
- uses: sigstore/cosign-installer@v3.4.0
- uses: sigstore/cosign-installer@v3.5.0
- name: Prepare
id: prep
run: |
@@ -142,7 +146,7 @@ jobs:
actions: read # for detecting the Github Actions environment.
id-token: write # for creating OIDC tokens for signing.
contents: write # for uploading attestations to GitHub releases.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
with:
provenance-name: "provenance.intoto.jsonl"
base64-subjects: "${{ needs.release-flagger.outputs.hashes }}"

View File

@@ -25,13 +25,16 @@ jobs:
fossa-api-key: 5ee8bf422db1471e0bcf2bcb289185de
github-token: ${{ github.token }}
scan-codeql:
runs-on:
group: "Default Larger Runners"
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:

View File

@@ -2,6 +2,94 @@
All notable changes to this project are documented in this file.
## 1.38.0
**Release date:** 2024-07-30
This release comes with several fixes and improvements. There is a new [Keptn
metrics provider](https://docs.flagger.app/usage/metrics#keptn) that can be used
for flexible grading logic and analysis.
The loadtester chart now supports ServiceAccount annotations and the Flagger
chart now supports specifying `honorLabels` for the PodMonitor.
Support for Kuma has been fixed and verified against Kuma 2.7.5. Also, the
Deployment scaling has been updated to use `Patch` instead of `Update` to avoid
intermittent conflict errors. Furthermore, a potential panic that could be
caused due to Prometheus returning a range vector has been fixed. Also, the
`request-duration` inbuilt query for Nginx has been updated to be more accurate.
Lastly, all Go dependencies, Alpine and Kubernetes libraries were updated.
#### Important
The update to Kubernetes libraries also brings an unwanted side-effect. Due to
a change in upstream Kubernetes, sidecar support is done through a new field,
which may be utilized by other services in your cluster. This would change the
hash calculated by Flagger between runs and trigger an unwanted Canary
analysis. Unfortunately, this is unavoidable. To get around this, users could
set the `.spec.suspend` field to be true before updating to this version and
switch it back when they update their application.
#### Improvements
- Bumps golang.org/x/net to v0.23.0
[#1628](https://github.com/fluxcd/flagger/pull/1628)
- feat: implement a Keptn metrics provider
[#1630](https://github.com/fluxcd/flagger/pull/1630)
- Update dependencies to Kubernetes 1.30
[#1638](https://github.com/fluxcd/flagger/pull/1638)
- loadtester: add support for annotation on service account
[#1649](https://github.com/fluxcd/flagger/pull/1649)
- Bump golang.org/x/net to v0.25.0 and other deps.
[#1653](https://github.com/fluxcd/flagger/pull/1653)
- Update Go dependencies and Alpine
[#1656](https://github.com/fluxcd/flagger/pull/1656)
- Helm - Add podMonitor.honor labels
[#1676](https://github.com/fluxcd/flagger/pull/1676)
- kuma: bump e2e version to 2.7.5
[#1683](https://github.com/fluxcd/flagger/pull/1683)
- Release loadtester 0.33.0
[#1690](https://github.com/fluxcd/flagger/pull/1690)
- Bump google.golang.org/grpc from 1.64.0 to 1.64.1
[#1675](https://github.com/fluxcd/flagger/pull/1675)
#### Fixes
- Use `Patch` instead of `Update` for Deployment scaling
[#1634](https://github.com/fluxcd/flagger/pull/1634)
- block panic when prom returns range vector
[#1637](https://github.com/fluxcd/flagger/pull/1637)
- Fix removal of empty keys from flagger chart
[#1657](https://github.com/fluxcd/flagger/pull/1657)
- doc: fix KEDA doc regarding namespaces
[#1666](https://github.com/fluxcd/flagger/pull/1666)
- Fix Nginx request-duration query
[#1686](https://github.com/fluxcd/flagger/pull/1686)
## 1.37.0
**Release date:** 2024-03-26
This release updates the Istio APIs to `v1beta1` and fixes several issues related
to Gloo routing and custom metrics.
Both Flagger and the load tester Go dependencies have been updated to fix various CVEs.
Flagger and the load tester are now built with Go 1.22.
#### Improvements
- Migrate Istio VirtualService/DestinationRule APIs to `v1beta1`
[#1602](https://github.com/fluxcd/flagger/pull/1602)
- Add `omitempty` to CRD statuses to allow better marshalling
[#1621](https://github.com/fluxcd/flagger/pull/1621)
- Update dependencies (Go 1.22)
[#1622](https://github.com/fluxcd/flagger/pull/1622)
- Update `google.golang.org/protobuf` to v1.33.0
[#1614](https://github.com/fluxcd/flagger/pull/1614)
#### Fixes
- Update reconciler to detect change in Gloo upstream spec
[#1617](https://github.com/fluxcd/flagger/pull/1617)
- Fix regression bug where query with no metric template returned an error
[#1611](https://github.com/fluxcd/flagger/pull/1611)
## 1.36.1
**Release date:** 2024-03-06
@@ -1329,7 +1417,7 @@ The upgrade procedure from 0.x to 1.0 can be found [here](https://docs.flagger.a
Two new resources were added to the API: `MetricTemplate` and `AlertProvider`.
The analysis can reference [metric templates](https://docs.flagger.app//usage/metrics#custom-metrics)
to query Prometheus, Datadog and AWS CloudWatch.
[Alerting](https://docs.flagger.app/v/master/usage/alerting#canary-configuration) can be configured on a per
[Alerting](https://docs.flagger.app/v/main/usage/alerting#canary-configuration) can be configured on a per
canary basis for Slack, MS Teams, Discord and Rocket.
#### Features
@@ -1493,7 +1581,7 @@ The upgrade procedure from 0.x to 1.0 can be found [here](https://docs.flagger.a
Two new resources were added to the API: `MetricTemplate` and `AlertProvider`.
The analysis can reference [metric templates](https://docs.flagger.app//usage/metrics#custom-metrics)
to query Prometheus, Datadog and AWS CloudWatch.
[Alerting](https://docs.flagger.app/v/master/usage/alerting#canary-configuration) can be configured on a per
[Alerting](https://docs.flagger.app/v/main/usage/alerting#canary-configuration) can be configured on a per
canary basis for Slack, MS Teams, Discord and Rocket.
#### Features

View File

@@ -1,4 +1,4 @@
FROM golang:1.21-alpine as builder
FROM golang:1.22-alpine as builder
ARG TARGETPLATFORM
ARG REVISON
@@ -21,7 +21,7 @@ RUN CGO_ENABLED=0 go build \
-ldflags "-s -w -X github.com/fluxcd/flagger/pkg/version.REVISION=${REVISON}" \
-a -o flagger ./cmd/flagger
FROM alpine:3.19
FROM alpine:3.20
RUN apk --no-cache add ca-certificates

View File

@@ -1,4 +1,4 @@
FROM golang:1.21-alpine as builder
FROM golang:1.22-alpine as builder
ARG TARGETPLATFORM
ARG TARGETARCH
@@ -6,19 +6,19 @@ ARG REVISION
RUN apk --no-cache add alpine-sdk perl curl bash tar
RUN HELM3_VERSION=3.12.0 && \
RUN HELM3_VERSION=3.15.3 && \
curl -sSL "https://get.helm.sh/helm-v${HELM3_VERSION}-linux-${TARGETARCH}.tar.gz" | tar xvz && \
chmod +x linux-${TARGETARCH}/helm && mv linux-${TARGETARCH}/helm /usr/local/bin/helm
RUN KUBECTL_VERSION=v1.28.0 && \
RUN KUBECTL_VERSION=v1.29.7 && \
curl -LO "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${TARGETARCH}/kubectl" && \
chmod +x kubectl && mv kubectl /usr/local/bin/kubectl
RUN GRPC_HEALTH_PROBE_VERSION=v0.4.19 && \
RUN GRPC_HEALTH_PROBE_VERSION=v0.4.28 && \
wget -qO /usr/local/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-${TARGETARCH} && \
chmod +x /usr/local/bin/grpc_health_probe
RUN GHZ_VERSION=0.117.0 && \
RUN GHZ_VERSION=0.120.0 && \
curl -sSL "https://github.com/bojand/ghz/archive/refs/tags/v${GHZ_VERSION}.tar.gz" | tar xz -C /tmp && \
cd /tmp/ghz-${GHZ_VERSION}/cmd/ghz && GOARCH=$TARGETARCH go build . && mv ghz /usr/local/bin && \
chmod +x /usr/local/bin/ghz

View File

@@ -6,19 +6,13 @@ build:
CGO_ENABLED=0 go build -a -o ./bin/flagger ./cmd/flagger
tidy:
rm -f go.sum; go mod tidy -compat=1.21
rm -f go.sum; go mod tidy -compat=1.22
vet:
go vet ./...
fmt:
go mod tidy
gofmt -l -s -w ./
goimports -l -w ./
test-fmt:
gofmt -l -s ./ | grep ".*\.go"; if [ "$$?" = "0" ]; then exit 1; fi
goimports -l ./ | grep ".*\.go"; if [ "$$?" = "0" ]; then exit 1; fi
go fmt ./...
codegen:
./hack/update-codegen.sh
@@ -26,10 +20,10 @@ codegen:
test-codegen:
./hack/verify-codegen.sh
test: test-fmt test-codegen
test: fmt test-codegen
go test ./...
test-coverage: test-fmt test-codegen
test-coverage: fmt test-codegen
go test -coverprofile cover.out ./...
go tool cover -html=cover.out
rm cover.out

View File

@@ -1135,6 +1135,9 @@ spec:
retries:
description: Number of retries for this webhook
type: number
disableTLS:
description: Disable TLS verification for this webhook
type: boolean
metadata:
description: Metadata (key-value pairs) for this webhook
type: object
@@ -1298,6 +1301,7 @@ spec:
- newrelic
- graphite
- dynatrace
- keptn
address:
description: API address of this provider
type: string

View File

@@ -22,7 +22,7 @@ spec:
serviceAccountName: flagger
containers:
- name: flagger
image: ghcr.io/fluxcd/flagger:1.36.1
image: ghcr.io/fluxcd/flagger:1.38.0
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -1,7 +1,7 @@
apiVersion: v1
name: flagger
version: 1.36.1
appVersion: 1.36.1
version: 1.38.0
appVersion: 1.38.0
kubeVersion: ">=1.19.0-0"
engine: gotpl
description: Flagger is a progressive delivery operator for Kubernetes

View File

@@ -157,6 +157,7 @@ The following tables lists the configurable parameters of the Flagger chart and
| `podMonitor.namespace` | Namespace where the PodMonitor is created | the same namespace |
| `podMonitor.interval` | Interval at which metrics should be scraped | `15s` |
| `podMonitor.podMonitor` | Additional labels to add to the PodMonitor | `{}` |
| `podMonitor.honorLabels` | If `true`, label conflicts are resolved by keeping label values from the scraped data and ignoring the conflicting server-side labels | `false` |
| `leaderElection.enabled` | If `true`, Flagger will run in HA mode | `false` |
| `leaderElection.replicaCount` | Number of replicas | `1` |
| `serviceAccount.create` | If `true`, Flagger will create service account | `true` |

View File

@@ -1135,6 +1135,9 @@ spec:
retries:
description: Number of retries for this webhook
type: number
disableTLS:
description: Disable TLS verification for this webhook
type: boolean
metadata:
description: Metadata (key-value pairs) for this webhook
type: object
@@ -1298,6 +1301,7 @@ spec:
- newrelic
- graphite
- dynatrace
- keptn
address:
description: API address of this provider
type: string

View File

@@ -4,8 +4,8 @@ kind: ServiceAccount
metadata:
name: {{ template "flagger.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
annotations:
{{- if .Values.serviceAccount.annotations }}
annotations:
{{ toYaml .Values.serviceAccount.annotations | indent 4 }}
{{- end }}
labels:

View File

@@ -48,12 +48,12 @@ spec:
imagePullSecrets:
- name: {{ .Values.image.pullSecret }}
{{- end }}
{{- if .Values.controlplane.kubeconfig.secretName }}
volumes:
{{- if .Values.controlplane.kubeconfig.secretName }}
- name: kubeconfig
secret:
secretName: "{{ .Values.controlplane.kubeconfig.secretName }}"
{{- end }}
{{- end }}
{{- if .Values.additionalVolumes }}
{{- toYaml .Values.additionalVolumes | nindent 8 -}}
{{- end }}
@@ -66,11 +66,11 @@ spec:
securityContext:
{{ toYaml .Values.securityContext.context | indent 12 }}
{{- end }}
{{- if .Values.controlplane.kubeconfig.secretName }}
volumeMounts:
{{- if .Values.controlplane.kubeconfig.secretName }}
- name: kubeconfig
mountPath: "/tmp/controlplane"
{{- end }}
{{- end }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:

View File

@@ -17,6 +17,7 @@ spec:
- interval: {{ .Values.podMonitor.interval }}
path: /metrics
port: http
honorLabels: {{ .Values.podMonitor.honorLabels }}
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}

View File

@@ -259,6 +259,19 @@ rules:
- update
- patch
- delete
- apiGroups:
- metrics.keptn.sh
resources:
- keptnmetrics
- analyses
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- nonResourceURLs:
- /version
verbs:

View File

@@ -5,7 +5,7 @@
image:
repository: ghcr.io/fluxcd/flagger
tag: 1.36.1
tag: 1.38.0
pullPolicy: IfNotPresent
pullSecret:
@@ -82,6 +82,7 @@ podMonitor:
namespace:
interval: 15s
additionalLabels: {}
honorLabels: false
#env:
#- name: SLACK_URL

View File

@@ -1,7 +1,7 @@
apiVersion: v1
name: loadtester
version: 0.31.0
appVersion: 0.31.0
version: 0.33.0
appVersion: 0.33.0
kubeVersion: ">=1.19.0-0"
engine: gotpl
description: Flagger's load testing services based on rakyll/hey and bojand/ghz that generates traffic during canary analysis when configured as a webhook.

View File

@@ -1,5 +1,5 @@
{{- if and (.Values.istio.enabled) (.Values.istio.gateway.enabled) }}
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: {{ include "loadtester.fullname" . }}

View File

@@ -1,5 +1,5 @@
{{- if .Values.istio.enabled }}
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: {{ include "loadtester.fullname" . }}

View File

@@ -51,4 +51,7 @@ metadata:
app.kubernetes.io/name: {{ template "loadtester.name" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- if .Values.rbac.serviceAccountAnnotations }}
annotations: {{ tpl (toYaml .Values.rbac.serviceAccountAnnotations) . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -2,7 +2,7 @@ replicaCount: 1
image:
repository: ghcr.io/fluxcd/flagger-loadtester
tag: 0.31.0
tag: 0.33.0
pullPolicy: IfNotPresent
pullSecret:
@@ -54,6 +54,8 @@ rbac:
# resources: ["pods"]
# verbs: ["list", "get"]
rules: []
# annotations to add to the service account
serviceAccountAnnotations: {}
# name of an existing service account to use - if not creating rbac resources
serviceAccountName: ""

View File

@@ -253,6 +253,7 @@ func main() {
fromEnv("EVENT_WEBHOOK_URL", eventWebhook),
clusterName,
noCrossNamespaceRefs,
cfg,
)
// leader election context
@@ -327,7 +328,7 @@ func startLeaderElection(ctx context.Context, run func(), ns string, kubeClient
id = id + "_" + string(uuid.NewUUID())
lock, err := resourcelock.New(
resourcelock.ConfigMapsLeasesResourceLock,
resourcelock.LeasesResourceLock,
ns,
configMapName,
kubeClient.CoreV1(),

View File

@@ -29,7 +29,7 @@ import (
"github.com/fluxcd/flagger/pkg/signals"
)
var VERSION = "0.31.0"
var VERSION = "0.33.0"
var (
logLevel string
port string

View File

@@ -600,7 +600,7 @@ spec:
For the above spec Flagger will generate the following virtual service:
```yaml
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend
@@ -653,7 +653,7 @@ spec:
For each destination in the virtual service a rule is generated:
```yaml
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: frontend-primary
@@ -664,7 +664,7 @@ spec:
tls:
mode: DISABLE
---
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: frontend-canary
@@ -751,7 +751,7 @@ spec:
Based on the above spec, Flagger will create the following virtual service:
```yaml
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: backend
@@ -777,7 +777,7 @@ spec:
Therefore, the following virtual service forwards the traffic to `/podinfo` by the above delegate VirtualService.
```yaml
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend

View File

@@ -374,7 +374,7 @@ helm upgrade -i flagger-grafana flagger/grafana \
Expose Grafana through the public gateway by creating a virtual service \(replace `example.com` with your domain\):
```yaml
apiVersion: networking.istio.io/v1alpha3
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: grafana

View File

@@ -20,6 +20,7 @@ Install Flagger:
```bash
helm repo add flagger https://flagger.app
kubectl create namespace flagger
helm upgrade -i flagger flagger/flagger \
--namespace flagger \
--set prometheus.install=true \
@@ -68,7 +69,7 @@ spec:
- type: prometheus
metadata:
name: prom-trigger
serverAddress: http://flagger-prometheus.flagger-system:9090
serverAddress: http://flagger-prometheus.flagger:9090
metricName: http_requests_total
query: sum(rate(http_requests_total{ app="podinfo" }[30s]))
threshold: '5'

View File

@@ -15,7 +15,7 @@ kumactl install control-plane | kubectl apply -f -
kumactl install observability --components "grafana,prometheus" | kubectl apply -f -
```
Install Flagger in the `kuma-system` namespace:
Install Flagger in the `kong-mesh-system` namespace:
```bash
kubectl apply -k github.com/fluxcd/flagger//kustomize/kuma

View File

@@ -668,3 +668,65 @@ Reference the template in the canary analysis:
max: 1000
interval: 1m
```
## Keptn
You can create custom metric checks using the Keptn provider.
This Provider allows to verify either the value of a single [KeptnMetric](https://keptn.sh/stable/docs/reference/crd-reference/metric/),
representing the value of a single metric,
or of a [Keptn Analysis](https://keptn.sh/stable/docs/reference/crd-reference/analysis/),
which provides a flexible grading logic for analysing and prioritising a number of different
metric values coming from different data sources.
This provider requires [Keptn](https://keptn.sh/stable/docs/installation/) to be installed in the cluster.
Example for a Keptn metric template:
```yaml
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: response-time
namespace: istio-system
spec:
provider:
type: keptn
query: keptnmetric/my-namespace/response-time/2m/reporter=destination
```
This will reference the `KeptnMetric` with the name `response-time` in
the namespace `my-namespace`, which could look like the following:
```yaml
apiVersion: metrics.keptn.sh/v1beta1
kind: KeptnMetric
metadata:
name: response-time
namespace: my-namespace
spec:
fetchIntervalSeconds: 10
provider:
name: my-prometheus-keptn-provider
query: histogram_quantile(0.8, sum by(le) (rate(http_server_request_latency_seconds_bucket{status_code='200',
job='simple-go-backend'}[5m[])))
```
The `query` contains the following components, which are divided by `/` characters:
```
<type>/<namespace>/<resource-name>/<timeframe>/<arguments>
```
* **type (required)**: Must be either `keptnmetric` or `analysis`.
* **namespace (required)**: The namespace of the referenced `KeptnMetric`/`AnalysisDefinition`.
* **resource-name (required):** The name of the referenced `KeptnMetric`/`AnalysisDefinition`.
* **timeframe (optional)**: The timeframe used for the Analysis.
This will usually be set to the same value as the analysis interval of a `Canary`.
Only relevant if the `type` is set to `analysis`.
* **arguments (optional)**: Arguments to be passed to an `Analysis`.
Arguments are passed as a list of key value pairs, separated by `;` characters,
e.g. `foo=bar;bar=foo`.
Only relevant if the `type` is set to `analysis`.
For the type `analysis`, the value returned by the provider is either `0`
(if the analysis failed), or `1` (analysis passed).

View File

@@ -124,7 +124,10 @@ Event payload (HTTP POST):
The event receiver can create alerts based on the received phase
(possible values: `Initialized`, `Waiting`, `Progressing`, `Promoting`, `Finalising`, `Succeeded` or `Failed`).
The webhook request can be retried by specifying a positive integer in the `retries` field.
Options:
* retries: The webhook request can be retried by specifying a positive integer in the `retries` field. This helps ensure reliability if the webhook fails due to transient network issues.
* disable TLS: Set `disableTLS` to `true` in the webhook spec to bypass TLS verification. This is useful in cases where the target service uses self-signed certificates, or you need to connect to an insecure service for testing purposes.
## Load Testing

72
go.mod
View File

@@ -1,39 +1,42 @@
module github.com/fluxcd/flagger
go 1.21
go 1.22.0
require (
cloud.google.com/go/monitoring v1.18.0
cloud.google.com/go/monitoring v1.19.0
github.com/Masterminds/semver/v3 v3.2.1
github.com/aws/aws-sdk-go v1.50.31
github.com/aws/aws-sdk-go v1.53.12
github.com/davecgh/go-spew v1.1.1
github.com/go-logr/zapr v1.3.0
github.com/google/go-cmp v0.6.0
github.com/googleapis/gax-go/v2 v2.12.2
github.com/hashicorp/go-retryablehttp v0.7.5
github.com/google/uuid v1.6.0
github.com/googleapis/gax-go/v2 v2.12.4
github.com/hashicorp/go-retryablehttp v0.7.7
github.com/influxdata/influxdb-client-go/v2 v2.13.0
github.com/prometheus/client_golang v1.19.0
github.com/prometheus/client_golang v1.19.1
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
google.golang.org/api v0.168.0
google.golang.org/genproto v0.0.0-20240304212257-790db918fca8
google.golang.org/grpc v1.62.0
google.golang.org/protobuf v1.32.0
golang.org/x/sync v0.7.0
google.golang.org/api v0.182.0
google.golang.org/genproto v0.0.0-20240528184218-531527333157
google.golang.org/grpc v1.64.1
google.golang.org/protobuf v1.34.1
gopkg.in/h2non/gock.v1 v1.1.2
k8s.io/api v0.27.11
k8s.io/apimachinery v0.27.11
k8s.io/client-go v0.27.11
k8s.io/code-generator v0.27.11
k8s.io/api v0.30.3
k8s.io/apimachinery v0.30.3
k8s.io/client-go v0.30.3
k8s.io/code-generator v0.30.3
k8s.io/klog/v2 v2.120.1
)
require (
cloud.google.com/go/compute v1.24.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/auth v0.4.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
@@ -42,11 +45,10 @@ require (
github.com/go-openapi/swag v0.22.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
@@ -72,26 +74,24 @@ require (
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/oauth2 v0.20.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.16.1 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240228224816-df926f6c8641 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

235
go.sum
View File

@@ -1,51 +1,42 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/monitoring v1.18.0 h1:NfkDLQDG2UR3WYZVQE8kwSbUIEyIqJUPl+aOQdFH1T4=
cloud.google.com/go/monitoring v1.18.0/go.mod h1:c92vVBCeq/OB4Ioyo+NbN2U7tlg5ZH41PZcdvfc+Lcg=
cloud.google.com/go/auth v0.4.2 h1:sb0eyLkhRtpq5jA+a8KWw0W70YcdVca7KJ8TM0AFYDg=
cloud.google.com/go/auth v0.4.2/go.mod h1:Kqvlz1cf1sNA0D+sYJnkPQOP+JMHkuHeIgVmCRtZOLc=
cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4=
cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/monitoring v1.19.0 h1:NCXf8hfQi+Kmr56QJezXRZ6GPb80ZI7El1XztyUuLQI=
cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/aws/aws-sdk-go v1.50.31 h1:gx2NRLLEDUmQFC4YUsfMUKkGCwpXVO8ijUecq/nOQGA=
github.com/aws/aws-sdk-go v1.50.31/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.53.12 h1:8f8K+YaTy2qwtGwVIo2Ftq22UCH96xQAX7Q0lyZKDiA=
github.com/aws/aws-sdk-go v1.53.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE=
github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -59,8 +50,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -70,32 +61,27 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.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 v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=
github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
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.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.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/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.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=
@@ -107,17 +93,16 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA=
github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg=
github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/influxdata/influxdb-client-go/v2 v2.13.0 h1:ioBbLmR5NMbAjP4UVA5r9b5xGjpABD7j65pI8kFphDM=
@@ -135,7 +120,6 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
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.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -145,6 +129,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
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=
@@ -156,16 +144,16 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo=
github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A=
github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk=
github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo=
github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E=
github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE=
github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk=
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.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
@@ -173,31 +161,22 @@ github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSz
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
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=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
@@ -208,7 +187,6 @@ go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGX
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -218,74 +196,49 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
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.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
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.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20200323222414-85ca7c5b95cd/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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.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.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
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=
@@ -294,43 +247,34 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
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.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
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=
google.golang.org/api v0.168.0 h1:MBRe+Ki4mMN93jhDDbpuRLjRddooArz4FeSObvUMmjY=
google.golang.org/api v0.168.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg=
google.golang.org/api v0.182.0 h1:if5fPvudRQ78GeRx3RayIoiuV7modtErPIZC/T2bIvE=
google.golang.org/api v0.182.0/go.mod h1:cGhjy4caqA5yXRzEhkHI8Y9mfyC2VLTlER2l08xaqtM=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20240304212257-790db918fca8 h1:Fe8QycXyEd9mJgnwB9kmw00WgB43eQ/xYO5C6gceybQ=
google.golang.org/genproto v0.0.0-20240304212257-790db918fca8/go.mod h1:yA7a1bW1kwl459Ol0m0lV4hLTfrL/7Bkk4Mj2Ir1mWI=
google.golang.org/genproto/googleapis/api v0.0.0-20240228224816-df926f6c8641 h1:SO1wX9btGFrwj9EzH3ocqfwiPVOxfv4ggAJajzlHA5s=
google.golang.org/genproto/googleapis/api v0.0.0-20240228224816-df926f6c8641/go.mod h1:wLupoVsUfYPgOMwjzhYFbaVklw/INms+dqTp0tc1fv8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 h1:Xs9lu+tLXxLIfuci70nG4cpwaRC+mRQPUL7LoIeDJC4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
google.golang.org/genproto v0.0.0-20240528184218-531527333157 h1:u7WMYrIrVvs0TF5yaKwKNbcJyySYf+HAIFXxWltJOXE=
google.golang.org/genproto v0.0.0-20240528184218-531527333157/go.mod h1:ubQlAQnzejB8uZzszhrTCU2Fyp6Vi7ZE5nn0c3W8+qQ=
google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e h1:SkdGTrROJl2jRGT/Fxv5QUf9jtdKCQh4KQJXbXVLAi0=
google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e/go.mod h1:LweJcLbyVij6rCex8YunD8DYR5VDonap/jYl3ZRxcIU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e h1:Elxv5MwEkCI9f5SkoL6afed6NTdxaGoAo39eANBwHL8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -340,51 +284,42 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.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.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.27.11 h1:IsGrWbXt7RkE+arc9GLQPYI5AtZkT+feBMorY+Nzx4I=
k8s.io/api v0.27.11/go.mod h1:SGqTcyqa0e+Db3pgyH6v+por5dO2OdTkKDCdD3Op3Ng=
k8s.io/apimachinery v0.27.11 h1:ivrKMN7JgdtKhay14S5UQlvilV3z6W+wjiSQTzyr5zc=
k8s.io/apimachinery v0.27.11/go.mod h1:IHu2ovJ60RqxyPSLmTel7KDLdOCRbpOxwtUBmwBnT/E=
k8s.io/client-go v0.27.11 h1:SZChXsDaN6lB5IYywCpvQs/ZUa5vK2NHkpEwUhoK3fQ=
k8s.io/client-go v0.27.11/go.mod h1:Rg3Yeuk9sX87gpVunVn3AsvMkGZfXuutTDC/jigBNUo=
k8s.io/code-generator v0.27.11 h1:J3SExe92VqSKMUSIbItJrTtPITOSWS58AqIbLwycNY0=
k8s.io/code-generator v0.27.11/go.mod h1:iyFD2q65bX/xrlrGzXi2kZXiBTbTDiAzEty3jq6a0NA=
k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4 h1:aClvVG6GbX10ISHcc24J+tqbr0S7fEe1MWkFJ7cWWCI=
k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k=
k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U=
k8s.io/code-generator v0.30.3 h1:bmtnLJKagDS5f5uOEpLyJiDfIMKXGMKgOLBdde+w0Mc=
k8s.io/code-generator v0.30.3/go.mod h1:PFgBiv+miFV7TZYp+RXgROkhA+sWYZ+mtpbMLofMke8=
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
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.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
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.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@@ -25,15 +25,23 @@ trap "cleanup" EXIT SIGINT
echo ">> Temporary output directory ${TEMP_DIR}"
# Ensure we can execute.
chmod +x ${CODEGEN_PKG}/generate-groups.sh
chmod +x ${CODEGEN_PKG}/generate-internal-groups.sh
PACKAGE_PATH_BASE="github.com/fluxcd/flagger"
${CODEGEN_PKG}/generate-groups.sh client,deepcopy,informer,lister \
github.com/fluxcd/flagger/pkg/client github.com/fluxcd/flagger/pkg/apis \
"flagger:v1beta1 appmesh:v1beta2 appmesh:v1beta1 istio:v1alpha3 smi:v1alpha1 smi:v1alpha2 smi:v1alpha3 gloo/gloo:v1 gloo/gateway:v1 projectcontour:v1 traefik:v1alpha1 kuma:v1alpha1 gatewayapi:v1beta1 gatewayapi:v1 keda:v1alpha1 apisix:v2" \
--output-base "${TEMP_DIR}" \
--go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt
mkdir -p "${TEMP_DIR}/${PACKAGE_PATH_BASE}/pkg/client/informers" \
"${TEMP_DIR}/${PACKAGE_PATH_BASE}/pkg/client/listers" \
"${TEMP_DIR}/${PACKAGE_PATH_BASE}/pkg/client/clientset"
# Ensure we can execute.
chmod +x ${CODEGEN_PKG}/kube_codegen.sh
source ${CODEGEN_PKG}/kube_codegen.sh kube::codegen::gen_client \
--output-dir "${TEMP_DIR}" \
--output-pkg "${PACKAGE_PATH_BASE}/pkg/client" \
--with-watch \
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \
./pkgs/apis
ls -lha $TEMP_DIR
# Copy everything back.
cp -r "${TEMP_DIR}/github.com/fluxcd/flagger/." "${SCRIPT_ROOT}/"
cp -r "${TEMP_DIR}/${PACKAGE_PATH_BASE}/." "${SCRIPT_ROOT}/"

View File

@@ -1135,6 +1135,9 @@ spec:
retries:
description: Number of retries for this webhook
type: number
disableTLS:
description: Disable TLS verification for this webhook
type: boolean
metadata:
description: Metadata (key-value pairs) for this webhook
type: object
@@ -1298,6 +1301,7 @@ spec:
- newrelic
- graphite
- dynatrace
- keptn
address:
description: API address of this provider
type: string

View File

@@ -9,4 +9,4 @@ resources:
images:
- name: ghcr.io/fluxcd/flagger
newName: ghcr.io/fluxcd/flagger
newTag: 1.36.1
newTag: 1.38.0

View File

@@ -241,6 +241,19 @@ rules:
- update
- patch
- delete
- apiGroups:
- metrics.keptn.sh
resources:
- keptnmetrics
- analyses
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- nonResourceURLs:
- /version
verbs:

View File

@@ -1,4 +1,4 @@
namespace: kuma-system
namespace: kong-mesh-system
bases:
- ../base/flagger/
patchesStrategicMerge:

View File

@@ -19,7 +19,7 @@ spec:
spec:
containers:
- name: loadtester
image: ghcr.io/fluxcd/flagger-loadtester:0.31.0
image: ghcr.io/fluxcd/flagger-loadtester:0.33.0
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -34,7 +34,7 @@ type AlertProvider struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AlertProviderSpec `json:"spec"`
Status AlertProviderStatus `json:"status"`
Status AlertProviderStatus `json:"status,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View File

@@ -21,7 +21,7 @@ import (
"time"
"github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
@@ -46,7 +46,7 @@ type Canary struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec CanarySpec `json:"spec"`
Status CanaryStatus `json:"status"`
Status CanaryStatus `json:"status,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -173,11 +173,11 @@ type CanaryService struct {
// TrafficPolicy attached to the generated Istio destination rules
// +optional
TrafficPolicy *istiov1alpha3.TrafficPolicy `json:"trafficPolicy,omitempty"`
TrafficPolicy *istiov1beta1.TrafficPolicy `json:"trafficPolicy,omitempty"`
// URI match conditions for the generated service
// +optional
Match []istiov1alpha3.HTTPMatchRequest `json:"match,omitempty"`
Match []istiov1beta1.HTTPMatchRequest `json:"match,omitempty"`
// Rewrite HTTP URIs for the generated service
// +optional
@@ -185,11 +185,11 @@ type CanaryService struct {
// Retries policy for the generated virtual service
// +optional
Retries *istiov1alpha3.HTTPRetry `json:"retries,omitempty"`
Retries *istiov1beta1.HTTPRetry `json:"retries,omitempty"`
// Headers operations for the generated Istio virtual service
// +optional
Headers *istiov1alpha3.Headers `json:"headers,omitempty"`
Headers *istiov1beta1.Headers `json:"headers,omitempty"`
// Mirror specifies the destination for request mirroring.
// Responses from this destination are dropped.
@@ -197,7 +197,7 @@ type CanaryService struct {
// Cross-Origin Resource Sharing policy for the generated Istio virtual service
// +optional
CorsPolicy *istiov1alpha3.CorsPolicy `json:"corsPolicy,omitempty"`
CorsPolicy *istiov1beta1.CorsPolicy `json:"corsPolicy,omitempty"`
// Mesh name of the generated App Mesh virtual nodes and virtual service
// +optional
@@ -275,7 +275,7 @@ type CanaryAnalysis struct {
// A/B testing HTTP header match conditions
// +optional
Match []istiov1alpha3.HTTPMatchRequest `json:"match,omitempty"`
Match []istiov1beta1.HTTPMatchRequest `json:"match,omitempty"`
// SessionAffinity represents the session affinity settings for a canary run.
// +optional
@@ -398,6 +398,10 @@ type CanaryWebhook struct {
// Number of retries for this webhook
// +optional
Retries int `json:"retries,omitempty"`
// Disable TLS verification for this webhook
// +optional
DisableTLS bool `json:"disableTls,omitempty"`
}
// CanaryWebhookPayload holds the deployment info and metadata sent to webhooks
@@ -516,10 +520,10 @@ func (r *HTTPRewrite) GetType() string {
return string(v1beta1.FullPathHTTPPathModifier)
}
// GetIstioRewrite returns a istiov1alpha3.HTTPRewrite object.
func (s *CanaryService) GetIstioRewrite() *istiov1alpha3.HTTPRewrite {
// GetIstioRewrite returns a istiov1beta1.HTTPRewrite object.
func (s *CanaryService) GetIstioRewrite() *istiov1beta1.HTTPRewrite {
if s.Rewrite != nil {
return &istiov1alpha3.HTTPRewrite{
return &istiov1beta1.HTTPRewrite{
Authority: s.Rewrite.Authority,
Uri: s.Rewrite.Uri,
}

View File

@@ -36,7 +36,7 @@ type MetricTemplate struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec MetricTemplateSpec `json:"spec"`
Status MetricTemplateStatus `json:"status"`
Status MetricTemplateStatus `json:"status,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View File

@@ -23,7 +23,7 @@ package v1beta1
import (
gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
v1 "k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -263,7 +263,7 @@ func (in *CanaryAnalysis) DeepCopyInto(out *CanaryAnalysis) {
}
if in.Match != nil {
in, out := &in.Match, &out.Match
*out = make([]v1alpha3.HTTPMatchRequest, len(*in))
*out = make([]istiov1beta1.HTTPMatchRequest, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -393,12 +393,12 @@ func (in *CanaryService) DeepCopyInto(out *CanaryService) {
}
if in.TrafficPolicy != nil {
in, out := &in.TrafficPolicy, &out.TrafficPolicy
*out = new(v1alpha3.TrafficPolicy)
*out = new(istiov1beta1.TrafficPolicy)
(*in).DeepCopyInto(*out)
}
if in.Match != nil {
in, out := &in.Match, &out.Match
*out = make([]v1alpha3.HTTPMatchRequest, len(*in))
*out = make([]istiov1beta1.HTTPMatchRequest, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
@@ -410,12 +410,12 @@ func (in *CanaryService) DeepCopyInto(out *CanaryService) {
}
if in.Retries != nil {
in, out := &in.Retries, &out.Retries
*out = new(v1alpha3.HTTPRetry)
*out = new(istiov1beta1.HTTPRetry)
**out = **in
}
if in.Headers != nil {
in, out := &in.Headers, &out.Headers
*out = new(v1alpha3.Headers)
*out = new(istiov1beta1.Headers)
(*in).DeepCopyInto(*out)
}
if in.Mirror != nil {
@@ -427,7 +427,7 @@ func (in *CanaryService) DeepCopyInto(out *CanaryService) {
}
if in.CorsPolicy != nil {
in, out := &in.CorsPolicy, &out.CorsPolicy
*out = new(v1alpha3.CorsPolicy)
*out = new(istiov1beta1.CorsPolicy)
(*in).DeepCopyInto(*out)
}
if in.Backends != nil {

View File

@@ -1,5 +1,5 @@
// proto: https://github.com/istio/api/blob/master/networking/v1alpha3/destination_rule.pb.go
package v1alpha3
// proto: https://github.com/istio/api/blob/master/networking/v1beta1/destination_rule.pb.go
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -21,7 +21,7 @@ type DestinationRule struct {
// balancing pool. For example, a simple load balancing policy for the
// ratings service would look as follows:
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -40,7 +40,7 @@ type DestinationRule struct {
// going to a subset named testversion that is composed of endpoints (e.g.,
// pods) with labels (version:v3).
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -68,7 +68,7 @@ type DestinationRule struct {
// traffic to port 80, while uses a round robin load balancing setting for
// traffic to the port 9080.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -172,7 +172,7 @@ type PortTrafficPolicy struct {
// subset named testversion that is composed of endpoints (e.g., pods) with
// labels (version:v3).
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -218,7 +218,7 @@ type Subset struct {
// For example, the following rule uses a round robin load balancing policy
// for all traffic going to the ratings service.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -235,7 +235,7 @@ type Subset struct {
// hashing-based load balancer for the same ratings service using the
// the User cookie as the hash key.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
// name: bookinfo-ratings
@@ -486,7 +486,7 @@ type HTTPCookie struct {
// For example, the following rule sets a limit of 100 connections to redis
// service called myredissrv with a connect timeout of 30ms
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -563,7 +563,7 @@ type HTTPSettings struct {
// scanned every 5 mins, such that any host that fails 7 consecutive times
// with 5XX error code will be ejected for 15 minutes.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -652,7 +652,7 @@ type OutlierDetection struct {
// For example, the following rule configures a client to use mutual TLS
// for connections to upstream database cluster.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -671,7 +671,7 @@ type OutlierDetection struct {
// The following rule configures a client to use TLS when talking to a
// foreign service whose domain matches *.foo.com.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -687,7 +687,7 @@ type OutlierDetection struct {
// The following rule configures a client to use Istio mutual TLS when talking
// to rating services.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//

View File

@@ -4,4 +4,4 @@
// +k8s:deepcopy-gen=package
// +groupName=networking.istio.io
package v1alpha3
package v1beta1

View File

@@ -1,4 +1,4 @@
package v1alpha3
package v1beta1
import (
"github.com/fluxcd/flagger/pkg/apis/istio"
@@ -8,7 +8,7 @@ import (
)
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: istio.GroupName, Version: "v1alpha3"}
var SchemeGroupVersion = schema.GroupVersion{Group: istio.GroupName, Version: "v1beta1"}
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {

View File

@@ -1,5 +1,5 @@
// proto: https://github.com/istio/api/blob/master/networking/v1alpha3/virtual_service.proto
package v1alpha3
// proto: https://github.com/istio/api/blob/master/networking/v1beta1/virtual_service.proto
package v1beta1
import (
"github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
@@ -31,7 +31,7 @@ type VirtualService struct {
// be rewritten to /newcatalog and sent to pods with label "version: v2".
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//
@@ -65,7 +65,7 @@ type VirtualService struct {
// `DestinationRule`.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -156,7 +156,7 @@ type VirtualServiceSpec struct {
// some to subset v2, in a kubernetes environment.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//
@@ -189,7 +189,7 @@ type VirtualServiceSpec struct {
// # And the associated DestinationRule
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: DestinationRule
// metadata:
//
@@ -220,7 +220,7 @@ type VirtualServiceSpec struct {
// not have an impact in resolving the name of the productpage service.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//
@@ -246,7 +246,7 @@ type VirtualServiceSpec struct {
// Service for wikipedia.org and set a timeout of 5s for http requests.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: ServiceEntry
// metadata:
//
@@ -263,7 +263,7 @@ type VirtualServiceSpec struct {
// protocol: HTTP
// resolution: DNS
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//
@@ -403,7 +403,7 @@ type HeaderOperations struct {
// starts with /ratings/v2/ and the request contains a "cookie" with value
// "user=jason".
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
// name: ratings-route
@@ -565,7 +565,7 @@ type PortSelector struct {
// server on port 5555.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//
@@ -636,7 +636,7 @@ type L4MatchAttributes struct {
// requests for /v1/getProductRatings API on the ratings service to
// /v1/bookRatings provided by the bookratings service.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
// name: ratings-route
@@ -668,7 +668,7 @@ type HTTPRedirect struct {
// demonstrates how to rewrite the URL prefix for api call (/ratings) to
// ratings service before making the actual API call.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
// name: ratings-route
@@ -700,7 +700,7 @@ type HTTPRewrite struct {
// calling ratings:v1 service, with a 2s timeout per retry attempt.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//
@@ -747,7 +747,7 @@ type HTTPRetry struct {
// Access-Control-Allow-Credentials header to false. In addition, it only
// exposes X-Foo-bar header and sets an expiry period of 1 day.
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
// name: ratings-route
@@ -826,7 +826,7 @@ type HTTPFaultInjection struct {
// in 10% of the requests to the "v1" version of the "reviews"
// service from all pods with label env: prod
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
// name: reviews-route
@@ -868,7 +868,7 @@ type InjectDelay struct {
// pre-specified error code. The following example will return an HTTP
// 400 error code for 10% of the requests to the "ratings" service "v1".
//
// apiVersion: networking.istio.io/v1alpha3
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
// name: ratings-route

View File

@@ -19,7 +19,7 @@ limitations under the License.
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
v1alpha1 "github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"

View File

@@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/util/retry"
@@ -154,12 +155,10 @@ func (c *DeploymentController) ScaleToZero(cd *flaggerv1.Canary) error {
return fmt.Errorf("deployment %s.%s get query error: %w", targetName, cd.Namespace, err)
}
depCopy := dep.DeepCopy()
depCopy.Spec.Replicas = int32p(0)
_, err = c.kubeClient.AppsV1().Deployments(dep.Namespace).Update(context.TODO(), depCopy, metav1.UpdateOptions{})
patch := []byte(fmt.Sprintf(`{"spec":{"replicas": %d}}`, 0))
_, err = c.kubeClient.AppsV1().Deployments(dep.Namespace).Patch(context.TODO(), dep.GetName(), types.MergePatchType, patch, metav1.PatchOptions{})
if err != nil {
return fmt.Errorf("deployment %s.%s update query error: %w", targetName, cd.Namespace, err)
return fmt.Errorf("deployment %s.%s patch query error: %w", targetName, cd.Namespace, err)
}
return nil
}
@@ -210,12 +209,11 @@ func (c *DeploymentController) ScaleFromZero(cd *flaggerv1.Canary) error {
}
}
}
depCopy := dep.DeepCopy()
depCopy.Spec.Replicas = replicas
_, err = c.kubeClient.AppsV1().Deployments(dep.Namespace).Update(context.TODO(), depCopy, metav1.UpdateOptions{})
patch := []byte(fmt.Sprintf(`{"spec":{"replicas": %d}}`, *replicas))
_, err = c.kubeClient.AppsV1().Deployments(dep.Namespace).Patch(context.TODO(), dep.GetName(), types.MergePatchType, patch, metav1.PatchOptions{})
if err != nil {
return fmt.Errorf("scaling up %s.%s to %v failed: %v", depCopy.GetName(), depCopy.Namespace, replicas, err)
return fmt.Errorf("scaling up %s.%s to %d failed: %v", dep.GetName(), dep.Namespace, *replicas, err)
}
return nil
}
@@ -388,11 +386,10 @@ func (c *DeploymentController) scale(cd *flaggerv1.Canary, replicas int32) error
return fmt.Errorf("deployment %s.%s query error: %w", targetName, cd.Namespace, err)
}
depCopy := dep.DeepCopy()
depCopy.Spec.Replicas = int32p(replicas)
_, err = c.kubeClient.AppsV1().Deployments(dep.Namespace).Update(context.TODO(), depCopy, metav1.UpdateOptions{})
patch := []byte(fmt.Sprintf(`{"spec":{"replicas": %d}}`, replicas))
_, err = c.kubeClient.AppsV1().Deployments(dep.Namespace).Patch(context.TODO(), dep.GetName(), types.MergePatchType, patch, metav1.PatchOptions{})
if err != nil {
return fmt.Errorf("scaling %s.%s to %v failed: %w", depCopy.GetName(), depCopy.Namespace, replicas, err)
return fmt.Errorf("scaling %s.%s to %d failed: %w", dep.GetName(), dep.Namespace, replicas, err)
}
return nil
}

View File

@@ -30,7 +30,7 @@ import (
gatewayapiv1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gatewayapi/v1"
gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gatewayapi/v1beta1"
gloov1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gloo/v1"
networkingv1alpha3 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3"
networkingv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1beta1"
kedav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/keda/v1alpha1"
kumav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/kuma/v1alpha1"
projectcontourv1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/projectcontour/v1"
@@ -53,7 +53,7 @@ type Interface interface {
GatewayapiV1beta1() gatewayapiv1beta1.GatewayapiV1beta1Interface
GatewayapiV1() gatewayapiv1.GatewayapiV1Interface
GlooV1() gloov1.GlooV1Interface
NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface
NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface
KedaV1alpha1() kedav1alpha1.KedaV1alpha1Interface
KumaV1alpha1() kumav1alpha1.KumaV1alpha1Interface
ProjectcontourV1() projectcontourv1.ProjectcontourV1Interface
@@ -66,22 +66,22 @@ type Interface interface {
// Clientset contains the clients for groups.
type Clientset struct {
*discovery.DiscoveryClient
apisixV2 *apisixv2.ApisixV2Client
appmeshV1beta2 *appmeshv1beta2.AppmeshV1beta2Client
appmeshV1beta1 *appmeshv1beta1.AppmeshV1beta1Client
flaggerV1beta1 *flaggerv1beta1.FlaggerV1beta1Client
gatewayV1 *gatewayv1.GatewayV1Client
gatewayapiV1beta1 *gatewayapiv1beta1.GatewayapiV1beta1Client
gatewayapiV1 *gatewayapiv1.GatewayapiV1Client
glooV1 *gloov1.GlooV1Client
networkingV1alpha3 *networkingv1alpha3.NetworkingV1alpha3Client
kedaV1alpha1 *kedav1alpha1.KedaV1alpha1Client
kumaV1alpha1 *kumav1alpha1.KumaV1alpha1Client
projectcontourV1 *projectcontourv1.ProjectcontourV1Client
splitV1alpha1 *splitv1alpha1.SplitV1alpha1Client
splitV1alpha2 *splitv1alpha2.SplitV1alpha2Client
splitV1alpha3 *splitv1alpha3.SplitV1alpha3Client
traefikV1alpha1 *traefikv1alpha1.TraefikV1alpha1Client
apisixV2 *apisixv2.ApisixV2Client
appmeshV1beta2 *appmeshv1beta2.AppmeshV1beta2Client
appmeshV1beta1 *appmeshv1beta1.AppmeshV1beta1Client
flaggerV1beta1 *flaggerv1beta1.FlaggerV1beta1Client
gatewayV1 *gatewayv1.GatewayV1Client
gatewayapiV1beta1 *gatewayapiv1beta1.GatewayapiV1beta1Client
gatewayapiV1 *gatewayapiv1.GatewayapiV1Client
glooV1 *gloov1.GlooV1Client
networkingV1beta1 *networkingv1beta1.NetworkingV1beta1Client
kedaV1alpha1 *kedav1alpha1.KedaV1alpha1Client
kumaV1alpha1 *kumav1alpha1.KumaV1alpha1Client
projectcontourV1 *projectcontourv1.ProjectcontourV1Client
splitV1alpha1 *splitv1alpha1.SplitV1alpha1Client
splitV1alpha2 *splitv1alpha2.SplitV1alpha2Client
splitV1alpha3 *splitv1alpha3.SplitV1alpha3Client
traefikV1alpha1 *traefikv1alpha1.TraefikV1alpha1Client
}
// ApisixV2 retrieves the ApisixV2Client
@@ -124,9 +124,9 @@ func (c *Clientset) GlooV1() gloov1.GlooV1Interface {
return c.glooV1
}
// NetworkingV1alpha3 retrieves the NetworkingV1alpha3Client
func (c *Clientset) NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface {
return c.networkingV1alpha3
// NetworkingV1beta1 retrieves the NetworkingV1beta1Client
func (c *Clientset) NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface {
return c.networkingV1beta1
}
// KedaV1alpha1 retrieves the KedaV1alpha1Client
@@ -240,7 +240,7 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset,
if err != nil {
return nil, err
}
cs.networkingV1alpha3, err = networkingv1alpha3.NewForConfigAndClient(&configShallowCopy, httpClient)
cs.networkingV1beta1, err = networkingv1beta1.NewForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
@@ -301,7 +301,7 @@ func New(c rest.Interface) *Clientset {
cs.gatewayapiV1beta1 = gatewayapiv1beta1.New(c)
cs.gatewayapiV1 = gatewayapiv1.New(c)
cs.glooV1 = gloov1.New(c)
cs.networkingV1alpha3 = networkingv1alpha3.New(c)
cs.networkingV1beta1 = networkingv1beta1.New(c)
cs.kedaV1alpha1 = kedav1alpha1.New(c)
cs.kumaV1alpha1 = kumav1alpha1.New(c)
cs.projectcontourV1 = projectcontourv1.New(c)

View File

@@ -36,8 +36,8 @@ import (
fakegatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gatewayapi/v1beta1/fake"
gloov1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gloo/v1"
fakegloov1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/gloo/v1/fake"
networkingv1alpha3 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3"
fakenetworkingv1alpha3 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3/fake"
networkingv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1beta1"
fakenetworkingv1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1beta1/fake"
kedav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/keda/v1alpha1"
fakekedav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/keda/v1alpha1/fake"
kumav1alpha1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/kuma/v1alpha1"
@@ -149,9 +149,9 @@ func (c *Clientset) GlooV1() gloov1.GlooV1Interface {
return &fakegloov1.FakeGlooV1{Fake: &c.Fake}
}
// NetworkingV1alpha3 retrieves the NetworkingV1alpha3Client
func (c *Clientset) NetworkingV1alpha3() networkingv1alpha3.NetworkingV1alpha3Interface {
return &fakenetworkingv1alpha3.FakeNetworkingV1alpha3{Fake: &c.Fake}
// NetworkingV1beta1 retrieves the NetworkingV1beta1Client
func (c *Clientset) NetworkingV1beta1() networkingv1beta1.NetworkingV1beta1Interface {
return &fakenetworkingv1beta1.FakeNetworkingV1beta1{Fake: &c.Fake}
}
// KedaV1alpha1 retrieves the KedaV1alpha1Client

View File

@@ -27,7 +27,7 @@ import (
gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
gatewayv1 "github.com/fluxcd/flagger/pkg/apis/gloo/gateway/v1"
gloov1 "github.com/fluxcd/flagger/pkg/apis/gloo/gloo/v1"
networkingv1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
networkingv1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
kedav1alpha1 "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1"
kumav1alpha1 "github.com/fluxcd/flagger/pkg/apis/kuma/v1alpha1"
projectcontourv1 "github.com/fluxcd/flagger/pkg/apis/projectcontour/v1"
@@ -54,7 +54,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{
gatewayapiv1beta1.AddToScheme,
gatewayapiv1.AddToScheme,
gloov1.AddToScheme,
networkingv1alpha3.AddToScheme,
networkingv1beta1.AddToScheme,
kedav1alpha1.AddToScheme,
kumav1alpha1.AddToScheme,
projectcontourv1.AddToScheme,

View File

@@ -27,7 +27,7 @@ import (
gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
gatewayv1 "github.com/fluxcd/flagger/pkg/apis/gloo/gateway/v1"
gloov1 "github.com/fluxcd/flagger/pkg/apis/gloo/gloo/v1"
networkingv1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
networkingv1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
kedav1alpha1 "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1"
kumav1alpha1 "github.com/fluxcd/flagger/pkg/apis/kuma/v1alpha1"
projectcontourv1 "github.com/fluxcd/flagger/pkg/apis/projectcontour/v1"
@@ -54,7 +54,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{
gatewayapiv1beta1.AddToScheme,
gatewayapiv1.AddToScheme,
gloov1.AddToScheme,
networkingv1alpha3.AddToScheme,
networkingv1beta1.AddToScheme,
kedav1alpha1.AddToScheme,
kumav1alpha1.AddToScheme,
projectcontourv1.AddToScheme,

View File

@@ -16,13 +16,13 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
"context"
"time"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
scheme "github.com/fluxcd/flagger/pkg/client/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
@@ -38,14 +38,14 @@ type DestinationRulesGetter interface {
// DestinationRuleInterface has methods to work with DestinationRule resources.
type DestinationRuleInterface interface {
Create(ctx context.Context, destinationRule *v1alpha3.DestinationRule, opts v1.CreateOptions) (*v1alpha3.DestinationRule, error)
Update(ctx context.Context, destinationRule *v1alpha3.DestinationRule, opts v1.UpdateOptions) (*v1alpha3.DestinationRule, error)
Create(ctx context.Context, destinationRule *v1beta1.DestinationRule, opts v1.CreateOptions) (*v1beta1.DestinationRule, error)
Update(ctx context.Context, destinationRule *v1beta1.DestinationRule, opts v1.UpdateOptions) (*v1beta1.DestinationRule, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha3.DestinationRule, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha3.DestinationRuleList, error)
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.DestinationRule, error)
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.DestinationRuleList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha3.DestinationRule, err error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.DestinationRule, err error)
DestinationRuleExpansion
}
@@ -56,7 +56,7 @@ type destinationRules struct {
}
// newDestinationRules returns a DestinationRules
func newDestinationRules(c *NetworkingV1alpha3Client, namespace string) *destinationRules {
func newDestinationRules(c *NetworkingV1beta1Client, namespace string) *destinationRules {
return &destinationRules{
client: c.RESTClient(),
ns: namespace,
@@ -64,8 +64,8 @@ func newDestinationRules(c *NetworkingV1alpha3Client, namespace string) *destina
}
// Get takes name of the destinationRule, and returns the corresponding destinationRule object, and an error if there is any.
func (c *destinationRules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha3.DestinationRule, err error) {
result = &v1alpha3.DestinationRule{}
func (c *destinationRules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.DestinationRule, err error) {
result = &v1beta1.DestinationRule{}
err = c.client.Get().
Namespace(c.ns).
Resource("destinationrules").
@@ -77,12 +77,12 @@ func (c *destinationRules) Get(ctx context.Context, name string, options v1.GetO
}
// List takes label and field selectors, and returns the list of DestinationRules that match those selectors.
func (c *destinationRules) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha3.DestinationRuleList, err error) {
func (c *destinationRules) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.DestinationRuleList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha3.DestinationRuleList{}
result = &v1beta1.DestinationRuleList{}
err = c.client.Get().
Namespace(c.ns).
Resource("destinationrules").
@@ -109,8 +109,8 @@ func (c *destinationRules) Watch(ctx context.Context, opts v1.ListOptions) (watc
}
// Create takes the representation of a destinationRule and creates it. Returns the server's representation of the destinationRule, and an error, if there is any.
func (c *destinationRules) Create(ctx context.Context, destinationRule *v1alpha3.DestinationRule, opts v1.CreateOptions) (result *v1alpha3.DestinationRule, err error) {
result = &v1alpha3.DestinationRule{}
func (c *destinationRules) Create(ctx context.Context, destinationRule *v1beta1.DestinationRule, opts v1.CreateOptions) (result *v1beta1.DestinationRule, err error) {
result = &v1beta1.DestinationRule{}
err = c.client.Post().
Namespace(c.ns).
Resource("destinationrules").
@@ -122,8 +122,8 @@ func (c *destinationRules) Create(ctx context.Context, destinationRule *v1alpha3
}
// Update takes the representation of a destinationRule and updates it. Returns the server's representation of the destinationRule, and an error, if there is any.
func (c *destinationRules) Update(ctx context.Context, destinationRule *v1alpha3.DestinationRule, opts v1.UpdateOptions) (result *v1alpha3.DestinationRule, err error) {
result = &v1alpha3.DestinationRule{}
func (c *destinationRules) Update(ctx context.Context, destinationRule *v1beta1.DestinationRule, opts v1.UpdateOptions) (result *v1beta1.DestinationRule, err error) {
result = &v1beta1.DestinationRule{}
err = c.client.Put().
Namespace(c.ns).
Resource("destinationrules").
@@ -163,8 +163,8 @@ func (c *destinationRules) DeleteCollection(ctx context.Context, opts v1.DeleteO
}
// Patch applies the patch and returns the patched destinationRule.
func (c *destinationRules) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha3.DestinationRule, err error) {
result = &v1alpha3.DestinationRule{}
func (c *destinationRules) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.DestinationRule, err error) {
result = &v1beta1.DestinationRule{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("destinationrules").

View File

@@ -17,4 +17,4 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v1alpha3
package v1beta1

View File

@@ -21,7 +21,7 @@ package fake
import (
"context"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
types "k8s.io/apimachinery/pkg/types"
@@ -31,29 +31,29 @@ import (
// FakeDestinationRules implements DestinationRuleInterface
type FakeDestinationRules struct {
Fake *FakeNetworkingV1alpha3
Fake *FakeNetworkingV1beta1
ns string
}
var destinationrulesResource = v1alpha3.SchemeGroupVersion.WithResource("destinationrules")
var destinationrulesResource = v1beta1.SchemeGroupVersion.WithResource("destinationrules")
var destinationrulesKind = v1alpha3.SchemeGroupVersion.WithKind("DestinationRule")
var destinationrulesKind = v1beta1.SchemeGroupVersion.WithKind("DestinationRule")
// Get takes name of the destinationRule, and returns the corresponding destinationRule object, and an error if there is any.
func (c *FakeDestinationRules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha3.DestinationRule, err error) {
func (c *FakeDestinationRules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.DestinationRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(destinationrulesResource, c.ns, name), &v1alpha3.DestinationRule{})
Invokes(testing.NewGetAction(destinationrulesResource, c.ns, name), &v1beta1.DestinationRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.DestinationRule), err
return obj.(*v1beta1.DestinationRule), err
}
// List takes label and field selectors, and returns the list of DestinationRules that match those selectors.
func (c *FakeDestinationRules) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha3.DestinationRuleList, err error) {
func (c *FakeDestinationRules) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.DestinationRuleList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(destinationrulesResource, destinationrulesKind, c.ns, opts), &v1alpha3.DestinationRuleList{})
Invokes(testing.NewListAction(destinationrulesResource, destinationrulesKind, c.ns, opts), &v1beta1.DestinationRuleList{})
if obj == nil {
return nil, err
@@ -63,8 +63,8 @@ func (c *FakeDestinationRules) List(ctx context.Context, opts v1.ListOptions) (r
if label == nil {
label = labels.Everything()
}
list := &v1alpha3.DestinationRuleList{ListMeta: obj.(*v1alpha3.DestinationRuleList).ListMeta}
for _, item := range obj.(*v1alpha3.DestinationRuleList).Items {
list := &v1beta1.DestinationRuleList{ListMeta: obj.(*v1beta1.DestinationRuleList).ListMeta}
for _, item := range obj.(*v1beta1.DestinationRuleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
@@ -80,31 +80,31 @@ func (c *FakeDestinationRules) Watch(ctx context.Context, opts v1.ListOptions) (
}
// Create takes the representation of a destinationRule and creates it. Returns the server's representation of the destinationRule, and an error, if there is any.
func (c *FakeDestinationRules) Create(ctx context.Context, destinationRule *v1alpha3.DestinationRule, opts v1.CreateOptions) (result *v1alpha3.DestinationRule, err error) {
func (c *FakeDestinationRules) Create(ctx context.Context, destinationRule *v1beta1.DestinationRule, opts v1.CreateOptions) (result *v1beta1.DestinationRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(destinationrulesResource, c.ns, destinationRule), &v1alpha3.DestinationRule{})
Invokes(testing.NewCreateAction(destinationrulesResource, c.ns, destinationRule), &v1beta1.DestinationRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.DestinationRule), err
return obj.(*v1beta1.DestinationRule), err
}
// Update takes the representation of a destinationRule and updates it. Returns the server's representation of the destinationRule, and an error, if there is any.
func (c *FakeDestinationRules) Update(ctx context.Context, destinationRule *v1alpha3.DestinationRule, opts v1.UpdateOptions) (result *v1alpha3.DestinationRule, err error) {
func (c *FakeDestinationRules) Update(ctx context.Context, destinationRule *v1beta1.DestinationRule, opts v1.UpdateOptions) (result *v1beta1.DestinationRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(destinationrulesResource, c.ns, destinationRule), &v1alpha3.DestinationRule{})
Invokes(testing.NewUpdateAction(destinationrulesResource, c.ns, destinationRule), &v1beta1.DestinationRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.DestinationRule), err
return obj.(*v1beta1.DestinationRule), err
}
// Delete takes name of the destinationRule and deletes it. Returns an error if one occurs.
func (c *FakeDestinationRules) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteActionWithOptions(destinationrulesResource, c.ns, name, opts), &v1alpha3.DestinationRule{})
Invokes(testing.NewDeleteActionWithOptions(destinationrulesResource, c.ns, name, opts), &v1beta1.DestinationRule{})
return err
}
@@ -113,17 +113,17 @@ func (c *FakeDestinationRules) Delete(ctx context.Context, name string, opts v1.
func (c *FakeDestinationRules) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(destinationrulesResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha3.DestinationRuleList{})
_, err := c.Fake.Invokes(action, &v1beta1.DestinationRuleList{})
return err
}
// Patch applies the patch and returns the patched destinationRule.
func (c *FakeDestinationRules) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha3.DestinationRule, err error) {
func (c *FakeDestinationRules) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.DestinationRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(destinationrulesResource, c.ns, name, pt, data, subresources...), &v1alpha3.DestinationRule{})
Invokes(testing.NewPatchSubresourceAction(destinationrulesResource, c.ns, name, pt, data, subresources...), &v1beta1.DestinationRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.DestinationRule), err
return obj.(*v1beta1.DestinationRule), err
}

View File

@@ -19,26 +19,26 @@ limitations under the License.
package fake
import (
v1alpha3 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/client/clientset/versioned/typed/istio/v1beta1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeNetworkingV1alpha3 struct {
type FakeNetworkingV1beta1 struct {
*testing.Fake
}
func (c *FakeNetworkingV1alpha3) DestinationRules(namespace string) v1alpha3.DestinationRuleInterface {
func (c *FakeNetworkingV1beta1) DestinationRules(namespace string) v1beta1.DestinationRuleInterface {
return &FakeDestinationRules{c, namespace}
}
func (c *FakeNetworkingV1alpha3) VirtualServices(namespace string) v1alpha3.VirtualServiceInterface {
func (c *FakeNetworkingV1beta1) VirtualServices(namespace string) v1beta1.VirtualServiceInterface {
return &FakeVirtualServices{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeNetworkingV1alpha3) RESTClient() rest.Interface {
func (c *FakeNetworkingV1beta1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@@ -21,7 +21,7 @@ package fake
import (
"context"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
types "k8s.io/apimachinery/pkg/types"
@@ -31,29 +31,29 @@ import (
// FakeVirtualServices implements VirtualServiceInterface
type FakeVirtualServices struct {
Fake *FakeNetworkingV1alpha3
Fake *FakeNetworkingV1beta1
ns string
}
var virtualservicesResource = v1alpha3.SchemeGroupVersion.WithResource("virtualservices")
var virtualservicesResource = v1beta1.SchemeGroupVersion.WithResource("virtualservices")
var virtualservicesKind = v1alpha3.SchemeGroupVersion.WithKind("VirtualService")
var virtualservicesKind = v1beta1.SchemeGroupVersion.WithKind("VirtualService")
// Get takes name of the virtualService, and returns the corresponding virtualService object, and an error if there is any.
func (c *FakeVirtualServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha3.VirtualService, err error) {
func (c *FakeVirtualServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.VirtualService, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(virtualservicesResource, c.ns, name), &v1alpha3.VirtualService{})
Invokes(testing.NewGetAction(virtualservicesResource, c.ns, name), &v1beta1.VirtualService{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.VirtualService), err
return obj.(*v1beta1.VirtualService), err
}
// List takes label and field selectors, and returns the list of VirtualServices that match those selectors.
func (c *FakeVirtualServices) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha3.VirtualServiceList, err error) {
func (c *FakeVirtualServices) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.VirtualServiceList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(virtualservicesResource, virtualservicesKind, c.ns, opts), &v1alpha3.VirtualServiceList{})
Invokes(testing.NewListAction(virtualservicesResource, virtualservicesKind, c.ns, opts), &v1beta1.VirtualServiceList{})
if obj == nil {
return nil, err
@@ -63,8 +63,8 @@ func (c *FakeVirtualServices) List(ctx context.Context, opts v1.ListOptions) (re
if label == nil {
label = labels.Everything()
}
list := &v1alpha3.VirtualServiceList{ListMeta: obj.(*v1alpha3.VirtualServiceList).ListMeta}
for _, item := range obj.(*v1alpha3.VirtualServiceList).Items {
list := &v1beta1.VirtualServiceList{ListMeta: obj.(*v1beta1.VirtualServiceList).ListMeta}
for _, item := range obj.(*v1beta1.VirtualServiceList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
@@ -80,31 +80,31 @@ func (c *FakeVirtualServices) Watch(ctx context.Context, opts v1.ListOptions) (w
}
// Create takes the representation of a virtualService and creates it. Returns the server's representation of the virtualService, and an error, if there is any.
func (c *FakeVirtualServices) Create(ctx context.Context, virtualService *v1alpha3.VirtualService, opts v1.CreateOptions) (result *v1alpha3.VirtualService, err error) {
func (c *FakeVirtualServices) Create(ctx context.Context, virtualService *v1beta1.VirtualService, opts v1.CreateOptions) (result *v1beta1.VirtualService, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(virtualservicesResource, c.ns, virtualService), &v1alpha3.VirtualService{})
Invokes(testing.NewCreateAction(virtualservicesResource, c.ns, virtualService), &v1beta1.VirtualService{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.VirtualService), err
return obj.(*v1beta1.VirtualService), err
}
// Update takes the representation of a virtualService and updates it. Returns the server's representation of the virtualService, and an error, if there is any.
func (c *FakeVirtualServices) Update(ctx context.Context, virtualService *v1alpha3.VirtualService, opts v1.UpdateOptions) (result *v1alpha3.VirtualService, err error) {
func (c *FakeVirtualServices) Update(ctx context.Context, virtualService *v1beta1.VirtualService, opts v1.UpdateOptions) (result *v1beta1.VirtualService, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(virtualservicesResource, c.ns, virtualService), &v1alpha3.VirtualService{})
Invokes(testing.NewUpdateAction(virtualservicesResource, c.ns, virtualService), &v1beta1.VirtualService{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.VirtualService), err
return obj.(*v1beta1.VirtualService), err
}
// Delete takes name of the virtualService and deletes it. Returns an error if one occurs.
func (c *FakeVirtualServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteActionWithOptions(virtualservicesResource, c.ns, name, opts), &v1alpha3.VirtualService{})
Invokes(testing.NewDeleteActionWithOptions(virtualservicesResource, c.ns, name, opts), &v1beta1.VirtualService{})
return err
}
@@ -113,17 +113,17 @@ func (c *FakeVirtualServices) Delete(ctx context.Context, name string, opts v1.D
func (c *FakeVirtualServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(virtualservicesResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha3.VirtualServiceList{})
_, err := c.Fake.Invokes(action, &v1beta1.VirtualServiceList{})
return err
}
// Patch applies the patch and returns the patched virtualService.
func (c *FakeVirtualServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha3.VirtualService, err error) {
func (c *FakeVirtualServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VirtualService, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(virtualservicesResource, c.ns, name, pt, data, subresources...), &v1alpha3.VirtualService{})
Invokes(testing.NewPatchSubresourceAction(virtualservicesResource, c.ns, name, pt, data, subresources...), &v1beta1.VirtualService{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha3.VirtualService), err
return obj.(*v1beta1.VirtualService), err
}

View File

@@ -16,7 +16,7 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
type DestinationRuleExpansion interface{}

View File

@@ -16,39 +16,39 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
"net/http"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
"github.com/fluxcd/flagger/pkg/client/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type NetworkingV1alpha3Interface interface {
type NetworkingV1beta1Interface interface {
RESTClient() rest.Interface
DestinationRulesGetter
VirtualServicesGetter
}
// NetworkingV1alpha3Client is used to interact with features provided by the networking.istio.io group.
type NetworkingV1alpha3Client struct {
// NetworkingV1beta1Client is used to interact with features provided by the networking.istio.io group.
type NetworkingV1beta1Client struct {
restClient rest.Interface
}
func (c *NetworkingV1alpha3Client) DestinationRules(namespace string) DestinationRuleInterface {
func (c *NetworkingV1beta1Client) DestinationRules(namespace string) DestinationRuleInterface {
return newDestinationRules(c, namespace)
}
func (c *NetworkingV1alpha3Client) VirtualServices(namespace string) VirtualServiceInterface {
func (c *NetworkingV1beta1Client) VirtualServices(namespace string) VirtualServiceInterface {
return newVirtualServices(c, namespace)
}
// NewForConfig creates a new NetworkingV1alpha3Client for the given config.
// NewForConfig creates a new NetworkingV1beta1Client for the given config.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*NetworkingV1alpha3Client, error) {
func NewForConfig(c *rest.Config) (*NetworkingV1beta1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
@@ -60,9 +60,9 @@ func NewForConfig(c *rest.Config) (*NetworkingV1alpha3Client, error) {
return NewForConfigAndClient(&config, httpClient)
}
// NewForConfigAndClient creates a new NetworkingV1alpha3Client for the given config and http client.
// NewForConfigAndClient creates a new NetworkingV1beta1Client for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*NetworkingV1alpha3Client, error) {
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*NetworkingV1beta1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
@@ -71,12 +71,12 @@ func NewForConfigAndClient(c *rest.Config, h *http.Client) (*NetworkingV1alpha3C
if err != nil {
return nil, err
}
return &NetworkingV1alpha3Client{client}, nil
return &NetworkingV1beta1Client{client}, nil
}
// NewForConfigOrDie creates a new NetworkingV1alpha3Client for the given config and
// NewForConfigOrDie creates a new NetworkingV1beta1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *NetworkingV1alpha3Client {
func NewForConfigOrDie(c *rest.Config) *NetworkingV1beta1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
@@ -84,13 +84,13 @@ func NewForConfigOrDie(c *rest.Config) *NetworkingV1alpha3Client {
return client
}
// New creates a new NetworkingV1alpha3Client for the given RESTClient.
func New(c rest.Interface) *NetworkingV1alpha3Client {
return &NetworkingV1alpha3Client{c}
// New creates a new NetworkingV1beta1Client for the given RESTClient.
func New(c rest.Interface) *NetworkingV1beta1Client {
return &NetworkingV1beta1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v1alpha3.SchemeGroupVersion
gv := v1beta1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
@@ -104,7 +104,7 @@ func setConfigDefaults(config *rest.Config) error {
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *NetworkingV1alpha3Client) RESTClient() rest.Interface {
func (c *NetworkingV1beta1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}

View File

@@ -16,13 +16,13 @@ limitations under the License.
// Code generated by client-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
"context"
"time"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
scheme "github.com/fluxcd/flagger/pkg/client/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
@@ -38,14 +38,14 @@ type VirtualServicesGetter interface {
// VirtualServiceInterface has methods to work with VirtualService resources.
type VirtualServiceInterface interface {
Create(ctx context.Context, virtualService *v1alpha3.VirtualService, opts v1.CreateOptions) (*v1alpha3.VirtualService, error)
Update(ctx context.Context, virtualService *v1alpha3.VirtualService, opts v1.UpdateOptions) (*v1alpha3.VirtualService, error)
Create(ctx context.Context, virtualService *v1beta1.VirtualService, opts v1.CreateOptions) (*v1beta1.VirtualService, error)
Update(ctx context.Context, virtualService *v1beta1.VirtualService, opts v1.UpdateOptions) (*v1beta1.VirtualService, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha3.VirtualService, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha3.VirtualServiceList, error)
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.VirtualService, error)
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.VirtualServiceList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha3.VirtualService, err error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VirtualService, err error)
VirtualServiceExpansion
}
@@ -56,7 +56,7 @@ type virtualServices struct {
}
// newVirtualServices returns a VirtualServices
func newVirtualServices(c *NetworkingV1alpha3Client, namespace string) *virtualServices {
func newVirtualServices(c *NetworkingV1beta1Client, namespace string) *virtualServices {
return &virtualServices{
client: c.RESTClient(),
ns: namespace,
@@ -64,8 +64,8 @@ func newVirtualServices(c *NetworkingV1alpha3Client, namespace string) *virtualS
}
// Get takes name of the virtualService, and returns the corresponding virtualService object, and an error if there is any.
func (c *virtualServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha3.VirtualService, err error) {
result = &v1alpha3.VirtualService{}
func (c *virtualServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.VirtualService, err error) {
result = &v1beta1.VirtualService{}
err = c.client.Get().
Namespace(c.ns).
Resource("virtualservices").
@@ -77,12 +77,12 @@ func (c *virtualServices) Get(ctx context.Context, name string, options v1.GetOp
}
// List takes label and field selectors, and returns the list of VirtualServices that match those selectors.
func (c *virtualServices) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha3.VirtualServiceList, err error) {
func (c *virtualServices) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.VirtualServiceList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha3.VirtualServiceList{}
result = &v1beta1.VirtualServiceList{}
err = c.client.Get().
Namespace(c.ns).
Resource("virtualservices").
@@ -109,8 +109,8 @@ func (c *virtualServices) Watch(ctx context.Context, opts v1.ListOptions) (watch
}
// Create takes the representation of a virtualService and creates it. Returns the server's representation of the virtualService, and an error, if there is any.
func (c *virtualServices) Create(ctx context.Context, virtualService *v1alpha3.VirtualService, opts v1.CreateOptions) (result *v1alpha3.VirtualService, err error) {
result = &v1alpha3.VirtualService{}
func (c *virtualServices) Create(ctx context.Context, virtualService *v1beta1.VirtualService, opts v1.CreateOptions) (result *v1beta1.VirtualService, err error) {
result = &v1beta1.VirtualService{}
err = c.client.Post().
Namespace(c.ns).
Resource("virtualservices").
@@ -122,8 +122,8 @@ func (c *virtualServices) Create(ctx context.Context, virtualService *v1alpha3.V
}
// Update takes the representation of a virtualService and updates it. Returns the server's representation of the virtualService, and an error, if there is any.
func (c *virtualServices) Update(ctx context.Context, virtualService *v1alpha3.VirtualService, opts v1.UpdateOptions) (result *v1alpha3.VirtualService, err error) {
result = &v1alpha3.VirtualService{}
func (c *virtualServices) Update(ctx context.Context, virtualService *v1beta1.VirtualService, opts v1.UpdateOptions) (result *v1beta1.VirtualService, err error) {
result = &v1beta1.VirtualService{}
err = c.client.Put().
Namespace(c.ns).
Resource("virtualservices").
@@ -163,8 +163,8 @@ func (c *virtualServices) DeleteCollection(ctx context.Context, opts v1.DeleteOp
}
// Patch applies the patch and returns the patched virtualService.
func (c *virtualServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha3.VirtualService, err error) {
result = &v1alpha3.VirtualService{}
func (c *virtualServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.VirtualService, err error) {
result = &v1beta1.VirtualService{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("virtualservices").

View File

@@ -29,13 +29,13 @@ import (
gatewayapiv1beta1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
v1 "github.com/fluxcd/flagger/pkg/apis/gloo/gateway/v1"
gloov1 "github.com/fluxcd/flagger/pkg/apis/gloo/gloo/v1"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
v1alpha1 "github.com/fluxcd/flagger/pkg/apis/keda/v1alpha1"
kumav1alpha1 "github.com/fluxcd/flagger/pkg/apis/kuma/v1alpha1"
projectcontourv1 "github.com/fluxcd/flagger/pkg/apis/projectcontour/v1"
smiv1alpha1 "github.com/fluxcd/flagger/pkg/apis/smi/v1alpha1"
v1alpha2 "github.com/fluxcd/flagger/pkg/apis/smi/v1alpha2"
smiv1alpha3 "github.com/fluxcd/flagger/pkg/apis/smi/v1alpha3"
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/smi/v1alpha3"
traefikv1alpha1 "github.com/fluxcd/flagger/pkg/apis/traefik/v1alpha1"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
@@ -119,11 +119,11 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case kumav1alpha1.SchemeGroupVersion.WithResource("trafficroutes"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Kuma().V1alpha1().TrafficRoutes().Informer()}, nil
// Group=networking.istio.io, Version=v1alpha3
case v1alpha3.SchemeGroupVersion.WithResource("destinationrules"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1alpha3().DestinationRules().Informer()}, nil
case v1alpha3.SchemeGroupVersion.WithResource("virtualservices"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1alpha3().VirtualServices().Informer()}, nil
// Group=networking.istio.io, Version=v1beta1
case istiov1beta1.SchemeGroupVersion.WithResource("destinationrules"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1beta1().DestinationRules().Informer()}, nil
case istiov1beta1.SchemeGroupVersion.WithResource("virtualservices"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1beta1().VirtualServices().Informer()}, nil
// Group=projectcontour.io, Version=v1
case projectcontourv1.SchemeGroupVersion.WithResource("httpproxies"):
@@ -138,7 +138,7 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Split().V1alpha2().TrafficSplits().Informer()}, nil
// Group=split.smi-spec.io, Version=v1alpha3
case smiv1alpha3.SchemeGroupVersion.WithResource("trafficsplits"):
case v1alpha3.SchemeGroupVersion.WithResource("trafficsplits"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Split().V1alpha3().TrafficSplits().Informer()}, nil
// Group=traefik.containo.us, Version=v1alpha1

View File

@@ -20,13 +20,13 @@ package istio
import (
internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces"
v1alpha3 "github.com/fluxcd/flagger/pkg/client/informers/externalversions/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/client/informers/externalversions/istio/v1beta1"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha3 provides access to shared informers for resources in V1alpha3.
V1alpha3() v1alpha3.Interface
// V1beta1 provides access to shared informers for resources in V1beta1.
V1beta1() v1beta1.Interface
}
type group struct {
@@ -40,7 +40,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha3 returns a new v1alpha3.Interface.
func (g *group) V1alpha3() v1alpha3.Interface {
return v1alpha3.New(g.factory, g.namespace, g.tweakListOptions)
// V1beta1 returns a new v1beta1.Interface.
func (g *group) V1beta1() v1beta1.Interface {
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
}

View File

@@ -16,16 +16,16 @@ limitations under the License.
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
"context"
time "time"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
versioned "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces"
v1alpha3 "github.com/fluxcd/flagger/pkg/client/listers/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/client/listers/istio/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
@@ -36,7 +36,7 @@ import (
// DestinationRules.
type DestinationRuleInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha3.DestinationRuleLister
Lister() v1beta1.DestinationRuleLister
}
type destinationRuleInformer struct {
@@ -62,16 +62,16 @@ func NewFilteredDestinationRuleInformer(client versioned.Interface, namespace st
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.NetworkingV1alpha3().DestinationRules(namespace).List(context.TODO(), options)
return client.NetworkingV1beta1().DestinationRules(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.NetworkingV1alpha3().DestinationRules(namespace).Watch(context.TODO(), options)
return client.NetworkingV1beta1().DestinationRules(namespace).Watch(context.TODO(), options)
},
},
&istiov1alpha3.DestinationRule{},
&istiov1beta1.DestinationRule{},
resyncPeriod,
indexers,
)
@@ -82,9 +82,9 @@ func (f *destinationRuleInformer) defaultInformer(client versioned.Interface, re
}
func (f *destinationRuleInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&istiov1alpha3.DestinationRule{}, f.defaultInformer)
return f.factory.InformerFor(&istiov1beta1.DestinationRule{}, f.defaultInformer)
}
func (f *destinationRuleInformer) Lister() v1alpha3.DestinationRuleLister {
return v1alpha3.NewDestinationRuleLister(f.Informer().GetIndexer())
func (f *destinationRuleInformer) Lister() v1beta1.DestinationRuleLister {
return v1beta1.NewDestinationRuleLister(f.Informer().GetIndexer())
}

View File

@@ -16,7 +16,7 @@ limitations under the License.
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces"

View File

@@ -16,16 +16,16 @@ limitations under the License.
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
"context"
time "time"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
versioned "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
internalinterfaces "github.com/fluxcd/flagger/pkg/client/informers/externalversions/internalinterfaces"
v1alpha3 "github.com/fluxcd/flagger/pkg/client/listers/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/client/listers/istio/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
@@ -36,7 +36,7 @@ import (
// VirtualServices.
type VirtualServiceInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha3.VirtualServiceLister
Lister() v1beta1.VirtualServiceLister
}
type virtualServiceInformer struct {
@@ -62,16 +62,16 @@ func NewFilteredVirtualServiceInformer(client versioned.Interface, namespace str
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.NetworkingV1alpha3().VirtualServices(namespace).List(context.TODO(), options)
return client.NetworkingV1beta1().VirtualServices(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.NetworkingV1alpha3().VirtualServices(namespace).Watch(context.TODO(), options)
return client.NetworkingV1beta1().VirtualServices(namespace).Watch(context.TODO(), options)
},
},
&istiov1alpha3.VirtualService{},
&istiov1beta1.VirtualService{},
resyncPeriod,
indexers,
)
@@ -82,9 +82,9 @@ func (f *virtualServiceInformer) defaultInformer(client versioned.Interface, res
}
func (f *virtualServiceInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&istiov1alpha3.VirtualService{}, f.defaultInformer)
return f.factory.InformerFor(&istiov1beta1.VirtualService{}, f.defaultInformer)
}
func (f *virtualServiceInformer) Lister() v1alpha3.VirtualServiceLister {
return v1alpha3.NewVirtualServiceLister(f.Informer().GetIndexer())
func (f *virtualServiceInformer) Lister() v1beta1.VirtualServiceLister {
return v1beta1.NewVirtualServiceLister(f.Informer().GetIndexer())
}

View File

@@ -16,10 +16,10 @@ limitations under the License.
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
@@ -30,7 +30,7 @@ import (
type DestinationRuleLister interface {
// List lists all DestinationRules in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error)
List(selector labels.Selector) (ret []*v1beta1.DestinationRule, err error)
// DestinationRules returns an object that can list and get DestinationRules.
DestinationRules(namespace string) DestinationRuleNamespaceLister
DestinationRuleListerExpansion
@@ -47,9 +47,9 @@ func NewDestinationRuleLister(indexer cache.Indexer) DestinationRuleLister {
}
// List lists all DestinationRules in the indexer.
func (s *destinationRuleLister) List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error) {
func (s *destinationRuleLister) List(selector labels.Selector) (ret []*v1beta1.DestinationRule, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha3.DestinationRule))
ret = append(ret, m.(*v1beta1.DestinationRule))
})
return ret, err
}
@@ -64,10 +64,10 @@ func (s *destinationRuleLister) DestinationRules(namespace string) DestinationRu
type DestinationRuleNamespaceLister interface {
// List lists all DestinationRules in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error)
List(selector labels.Selector) (ret []*v1beta1.DestinationRule, err error)
// Get retrieves the DestinationRule from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v1alpha3.DestinationRule, error)
Get(name string) (*v1beta1.DestinationRule, error)
DestinationRuleNamespaceListerExpansion
}
@@ -79,21 +79,21 @@ type destinationRuleNamespaceLister struct {
}
// List lists all DestinationRules in the indexer for a given namespace.
func (s destinationRuleNamespaceLister) List(selector labels.Selector) (ret []*v1alpha3.DestinationRule, err error) {
func (s destinationRuleNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.DestinationRule, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha3.DestinationRule))
ret = append(ret, m.(*v1beta1.DestinationRule))
})
return ret, err
}
// Get retrieves the DestinationRule from the indexer for a given namespace and name.
func (s destinationRuleNamespaceLister) Get(name string) (*v1alpha3.DestinationRule, error) {
func (s destinationRuleNamespaceLister) Get(name string) (*v1beta1.DestinationRule, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha3.Resource("destinationrule"), name)
return nil, errors.NewNotFound(v1beta1.Resource("destinationrule"), name)
}
return obj.(*v1alpha3.DestinationRule), nil
return obj.(*v1beta1.DestinationRule), nil
}

View File

@@ -16,7 +16,7 @@ limitations under the License.
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
// DestinationRuleListerExpansion allows custom methods to be added to
// DestinationRuleLister.

View File

@@ -16,10 +16,10 @@ limitations under the License.
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha3
package v1beta1
import (
v1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
v1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
@@ -30,7 +30,7 @@ import (
type VirtualServiceLister interface {
// List lists all VirtualServices in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error)
List(selector labels.Selector) (ret []*v1beta1.VirtualService, err error)
// VirtualServices returns an object that can list and get VirtualServices.
VirtualServices(namespace string) VirtualServiceNamespaceLister
VirtualServiceListerExpansion
@@ -47,9 +47,9 @@ func NewVirtualServiceLister(indexer cache.Indexer) VirtualServiceLister {
}
// List lists all VirtualServices in the indexer.
func (s *virtualServiceLister) List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error) {
func (s *virtualServiceLister) List(selector labels.Selector) (ret []*v1beta1.VirtualService, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha3.VirtualService))
ret = append(ret, m.(*v1beta1.VirtualService))
})
return ret, err
}
@@ -64,10 +64,10 @@ func (s *virtualServiceLister) VirtualServices(namespace string) VirtualServiceN
type VirtualServiceNamespaceLister interface {
// List lists all VirtualServices in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error)
List(selector labels.Selector) (ret []*v1beta1.VirtualService, err error)
// Get retrieves the VirtualService from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v1alpha3.VirtualService, error)
Get(name string) (*v1beta1.VirtualService, error)
VirtualServiceNamespaceListerExpansion
}
@@ -79,21 +79,21 @@ type virtualServiceNamespaceLister struct {
}
// List lists all VirtualServices in the indexer for a given namespace.
func (s virtualServiceNamespaceLister) List(selector labels.Selector) (ret []*v1alpha3.VirtualService, err error) {
func (s virtualServiceNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.VirtualService, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha3.VirtualService))
ret = append(ret, m.(*v1beta1.VirtualService))
})
return ret, err
}
// Get retrieves the VirtualService from the indexer for a given namespace and name.
func (s virtualServiceNamespaceLister) Get(name string) (*v1alpha3.VirtualService, error) {
func (s virtualServiceNamespaceLister) Get(name string) (*v1beta1.VirtualService, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha3.Resource("virtualservice"), name)
return nil, errors.NewNotFound(v1beta1.Resource("virtualservice"), name)
}
return obj.(*v1alpha3.VirtualService), nil
return obj.(*v1beta1.VirtualService), nil
}

View File

@@ -21,6 +21,8 @@ import (
"sync"
"time"
"k8s.io/client-go/rest"
"github.com/google/go-cmp/cmp"
"go.uber.org/zap"
corev1 "k8s.io/api/core/v1"
@@ -49,6 +51,7 @@ const controllerAgentName = "flagger"
// Controller is managing the canary objects and schedules canary deployments
type Controller struct {
kubeConfig *rest.Config
kubeClient kubernetes.Interface
flaggerClient clientset.Interface
flaggerInformers Informers
@@ -91,6 +94,7 @@ func NewController(
eventWebhook string,
clusterName string,
noCrossNamespaceRefs bool,
kubeConfig *rest.Config,
) *Controller {
logger.Debug("Creating event broadcaster")
flaggerscheme.AddToScheme(scheme.Scheme)
@@ -105,6 +109,7 @@ func NewController(
recorder.SetInfo(version, meshProvider)
ctrl := &Controller{
kubeConfig: kubeConfig,
kubeClient: kubeClient,
flaggerClient: flaggerClient,
flaggerInformers: flaggerInformers,

View File

@@ -32,7 +32,7 @@ import (
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
istiov1alpha1 "github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
"github.com/fluxcd/flagger/pkg/canary"
clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
fakeFlagger "github.com/fluxcd/flagger/pkg/client/clientset/versioned/fake"
@@ -327,7 +327,7 @@ func newDaemonSetTestCanaryAB() *flaggerv1.Canary {
}, Analysis: &flaggerv1.CanaryAnalysis{
Threshold: 10,
Iterations: 10,
Match: []istiov1alpha3.HTTPMatchRequest{
Match: []istiov1beta1.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"x-user-type": {

View File

@@ -37,7 +37,7 @@ import (
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
istiov1alpha1 "github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
"github.com/fluxcd/flagger/pkg/canary"
clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
fakeFlagger "github.com/fluxcd/flagger/pkg/client/clientset/versioned/fake"
@@ -367,7 +367,7 @@ func newDeploymentTestCanaryAB() *flaggerv1.Canary {
}, Analysis: &flaggerv1.CanaryAnalysis{
Threshold: 10,
Iterations: 10,
Match: []istiov1alpha3.HTTPMatchRequest{
Match: []istiov1beta1.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"x-user-type": {

View File

@@ -74,7 +74,7 @@ func (c *Controller) checkMetricProviderAvailability(canary *flaggerv1.Canary) e
}
factory := providers.Factory{}
provider, err := factory.Provider(metric.Interval, template.Spec.Provider, credentials)
provider, err := factory.Provider(metric.Interval, template.Spec.Provider, credentials, c.kubeConfig)
if err != nil {
return fmt.Errorf("metric template %s.%s provider %s error: %v",
metric.TemplateRef.Name, namespace, template.Spec.Provider.Type, err)
@@ -260,7 +260,7 @@ func (c *Controller) runMetricChecks(canary *flaggerv1.Canary) bool {
}
factory := providers.Factory{}
provider, err := factory.Provider(metric.Interval, template.Spec.Provider, credentials)
provider, err := factory.Provider(metric.Interval, template.Spec.Provider, credentials, c.kubeConfig)
if err != nil {
c.recordEventErrorf(canary, "Metric template %s.%s provider %s error: %v",
metric.TemplateRef.Name, namespace, template.Spec.Provider.Type, err)
@@ -306,8 +306,8 @@ func (c *Controller) runMetricChecks(canary *flaggerv1.Canary) bool {
canary.Name, canary.Namespace, metric.Name, val, metric.Threshold)
return false
}
} else if metric.Name != "request-success-rate" && metric.Name != "request-duration" {
c.recordEventErrorf(canary, "Metric query failed for no usable metrics template were configured")
} else if metric.Name != "request-success-rate" && metric.Name != "request-duration" && metric.Query == "" {
c.recordEventErrorf(canary, "Metric query failed for no usable metrics template and query were configured")
return false
}
}

View File

@@ -88,7 +88,8 @@ func TestController_runMetricChecks(t *testing.T) {
t.Run("customVariables", func(t *testing.T) {
ctrl := newDeploymentFixture(nil).ctrl
analysis := &flaggerv1.CanaryAnalysis{Metrics: []flaggerv1.CanaryMetric{{
Name: "", TemplateVariables: map[string]string{
Name: "",
TemplateVariables: map[string]string{
"first": "abc",
"second": "def",
},
@@ -139,4 +140,46 @@ func TestController_runMetricChecks(t *testing.T) {
}
assert.Equal(t, true, ctrl.runMetricChecks(canary))
})
t.Run("no metric Template is defined, but a query is specified", func(t *testing.T) {
ctrl := newDeploymentFixture(nil).ctrl
analysis := &flaggerv1.CanaryAnalysis{Metrics: []flaggerv1.CanaryMetric{{
Name: "undefined metric",
ThresholdRange: &flaggerv1.CanaryThresholdRange{
Min: toFloatPtr(0),
Max: toFloatPtr(100),
},
Query: ">- sum(logback_events_total{level=\"error\", job=\"some-app\"}) <= bool 0",
}}}
canary := &flaggerv1.Canary{
ObjectMeta: metav1.ObjectMeta{Namespace: "default"},
Spec: flaggerv1.CanarySpec{Analysis: analysis},
}
assert.Equal(t, true, ctrl.runMetricChecks(canary))
})
t.Run("both have metric Template and query", func(t *testing.T) {
ctrl := newDeploymentFixture(nil).ctrl
analysis := &flaggerv1.CanaryAnalysis{Metrics: []flaggerv1.CanaryMetric{{
Name: "",
TemplateVariables: map[string]string{
"first": "abc",
"second": "def",
},
TemplateRef: &flaggerv1.CrossNamespaceObjectReference{
Name: "custom-vars",
Namespace: "default",
},
ThresholdRange: &flaggerv1.CanaryThresholdRange{
Min: toFloatPtr(0),
Max: toFloatPtr(100),
},
Query: ">- sum(logback_events_total{level=\"error\", job=\"some-app\"}) <= bool 0",
}}}
canary := &flaggerv1.Canary{
ObjectMeta: metav1.ObjectMeta{Namespace: "default"},
Spec: flaggerv1.CanarySpec{Analysis: analysis},
}
assert.Equal(t, true, ctrl.runMetricChecks(canary))
})
}

View File

@@ -18,10 +18,12 @@ package controller
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"time"
@@ -32,7 +34,22 @@ import (
"github.com/fluxcd/flagger/pkg/canary"
)
func callWebhook(webhook string, payload interface{}, timeout string, retries int) error {
func newHTTPClient(retries int, timeout time.Duration, disableTls bool) *retryablehttp.Client {
httpClient := retryablehttp.NewClient()
httpClient.RetryMax = retries
httpClient.Logger = nil
httpClient.HTTPClient.Timeout = timeout
if disableTls {
httpClient.HTTPClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
}
return httpClient
}
func callWebhook(webhook string, payload interface{}, timeout string, retries int, disableTls bool) error {
payloadBin, err := json.Marshal(payload)
if err != nil {
return err
@@ -43,17 +60,6 @@ func callWebhook(webhook string, payload interface{}, timeout string, retries in
return err
}
httpClient := retryablehttp.NewClient()
httpClient.RetryMax = retries
httpClient.Logger = nil
req, err := retryablehttp.NewRequest("POST", hook.String(), bytes.NewBuffer(payloadBin))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
if timeout == "" {
timeout = "10s"
}
@@ -62,7 +68,13 @@ func callWebhook(webhook string, payload interface{}, timeout string, retries in
return err
}
httpClient.HTTPClient.Timeout = t
httpClient := newHTTPClient(retries, t, disableTls)
req, err := retryablehttp.NewRequest("POST", hook.String(), bytes.NewBuffer(payloadBin))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
r, err := httpClient.Do(req)
if err != nil {
@@ -100,7 +112,7 @@ func CallWebhook(canary flaggerv1.Canary, phase flaggerv1.CanaryPhase, w flagger
w.Timeout = "10s"
}
return callWebhook(w.URL, payload, w.Timeout, w.Retries)
return callWebhook(w.URL, payload, w.Timeout, w.Retries, w.DisableTLS)
}
func CallEventWebhook(r *flaggerv1.Canary, w flaggerv1.CanaryWebhook, message, eventtype string) error {
@@ -126,7 +138,7 @@ func CallEventWebhook(r *flaggerv1.Canary, w flaggerv1.CanaryWebhook, message, e
payload.Metadata[key] = value
}
}
return callWebhook(w.URL, payload, "5s", w.Retries)
return callWebhook(w.URL, payload, "5s", w.Retries, w.DisableTLS)
}
func canaryChecksum(c flaggerv1.Canary) string {

View File

@@ -289,3 +289,22 @@ func TestCallWebhook_Retries(t *testing.T) {
flaggerv1.CanaryPhaseProgressing, hook)
require.NoError(t, err)
}
func TestCallWebhook_DisableTLS(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusAccepted)
}))
defer ts.Close()
hook := flaggerv1.CanaryWebhook{
Name: "validation",
URL: ts.URL,
DisableTLS: true,
}
err := CallWebhook(
flaggerv1.Canary{
ObjectMeta: metav1.ObjectMeta{
Name: "podinfo", Namespace: corev1.NamespaceDefault}},
flaggerv1.CanaryPhaseProgressing, hook)
require.NoError(t, err)
}

View File

@@ -33,7 +33,7 @@ var kumaQueries = map[string]string{
sum(
rate(
envoy_cluster_upstream_rq{
envoy_cluster_name=~"{{ target }}-canary_{{ namespace }}_svc_[0-9a-zA-Z-]+",
service=~"{{ target }}-canary_{{ namespace }}_svc_[0-9a-zA-Z-]+",
envoy_response_code!~"5.*"
}[{{ interval }}]
)
@@ -42,7 +42,7 @@ var kumaQueries = map[string]string{
sum(
rate(
envoy_cluster_upstream_rq{
envoy_cluster_name=~"{{ target }}-canary_{{ namespace }}_svc_[0-9a-zA-Z-]+",
service=~"{{ target }}-canary_{{ namespace }}_svc_[0-9a-zA-Z-]+",
}[{{ interval }}]
)
)
@@ -53,7 +53,7 @@ var kumaQueries = map[string]string{
sum(
rate(
envoy_cluster_upstream_rq_time_bucket{
envoy_cluster_name=~"{{ target }}-canary_{{ namespace }}_svc_[0-9a-zA-Z-]+",
service=~"{{ target }}-canary_{{ namespace }}_svc_[0-9a-zA-Z-]+",
}[{{ interval }}]
)
) by (le)

View File

@@ -30,7 +30,7 @@ import (
)
func TestKumaObserver_GetRequestSuccessRate(t *testing.T) {
expected := ` sum( rate( envoy_cluster_upstream_rq{ envoy_cluster_name=~"podinfo-canary_default_svc_[0-9a-zA-Z-]+", envoy_response_code!~"5.*" }[1m] ) ) / sum( rate( envoy_cluster_upstream_rq{ envoy_cluster_name=~"podinfo-canary_default_svc_[0-9a-zA-Z-]+", }[1m] ) ) * 100`
expected := ` sum( rate( envoy_cluster_upstream_rq{ service=~"podinfo-canary_default_svc_[0-9a-zA-Z-]+", envoy_response_code!~"5.*" }[1m] ) ) / sum( rate( envoy_cluster_upstream_rq{ service=~"podinfo-canary_default_svc_[0-9a-zA-Z-]+", }[1m] ) ) * 100`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
promql := r.URL.Query()["query"][0]
@@ -65,7 +65,7 @@ func TestKumaObserver_GetRequestSuccessRate(t *testing.T) {
}
func TestKumaObserver_GetRequestDuration(t *testing.T) {
expected := ` histogram_quantile( 0.99, sum( rate( envoy_cluster_upstream_rq_time_bucket{ envoy_cluster_name=~"podinfo-canary_default_svc_[0-9a-zA-Z-]+", }[1m] ) ) by (le) )`
expected := ` histogram_quantile( 0.99, sum( rate( envoy_cluster_upstream_rq_time_bucket{ service=~"podinfo-canary_default_svc_[0-9a-zA-Z-]+", }[1m] ) ) by (le) )`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
promql := r.URL.Query()["query"][0]

View File

@@ -50,7 +50,7 @@ var nginxQueries = map[string]string{
"request-duration": `
sum(
rate(
nginx_ingress_controller_ingress_upstream_latency_seconds_sum{
nginx_ingress_controller_response_duration_seconds_sum{
namespace="{{ namespace }}",
ingress="{{ ingress }}",
canary!=""
@@ -60,7 +60,7 @@ var nginxQueries = map[string]string{
/
sum(
rate(
nginx_ingress_controller_ingress_upstream_latency_seconds_count{
nginx_ingress_controller_response_duration_seconds_count{
namespace="{{ namespace }}",
ingress="{{ ingress }}",
canary!=""

View File

@@ -89,7 +89,7 @@ func TestNginxObserver_GetRequestSuccessRate(t *testing.T) {
}
func TestNginxObserver_GetRequestDuration(t *testing.T) {
expected := ` sum( rate( nginx_ingress_controller_ingress_upstream_latency_seconds_sum{ namespace="nginx", ingress="podinfo", canary!="" }[1m] ) ) / sum( rate( nginx_ingress_controller_ingress_upstream_latency_seconds_count{ namespace="nginx", ingress="podinfo", canary!="" }[1m] ) ) * 1000`
expected := ` sum( rate( nginx_ingress_controller_response_duration_seconds_sum{ namespace="nginx", ingress="podinfo", canary!="" }[1m] ) ) / sum( rate( nginx_ingress_controller_response_duration_seconds_count{ namespace="nginx", ingress="podinfo", canary!="" }[1m] ) ) * 1000`
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
promql := r.URL.Query()["query"][0]

View File

@@ -19,5 +19,6 @@ package providers
import "errors"
var (
ErrNoValuesFound = errors.New("no values found")
ErrNoValuesFound = errors.New("no values found")
ErrMultipleValuesReturned = errors.New("query returned multiple values")
)

View File

@@ -18,15 +18,12 @@ package providers
import (
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
rest "k8s.io/client-go/rest"
)
type Factory struct{}
func (factory Factory) Provider(
metricInterval string,
provider flaggerv1.MetricTemplateProvider,
credentials map[string][]byte,
) (Interface, error) {
func (factory Factory) Provider(metricInterval string, provider flaggerv1.MetricTemplateProvider, credentials map[string][]byte, config *rest.Config) (Interface, error) {
switch provider.Type {
case "prometheus":
return NewPrometheusProvider(provider, credentials)
@@ -44,6 +41,8 @@ func (factory Factory) Provider(
return NewInfluxdbProvider(provider, credentials)
case "dynatrace":
return NewDynatraceProvider(metricInterval, provider, credentials)
case "keptn":
return NewKeptnProvider(config)
default:
return NewPrometheusProvider(provider, credentials)
}

View File

@@ -0,0 +1,256 @@
package providers
import (
"context"
"errors"
"fmt"
"k8s.io/klog/v2"
"strconv"
"strings"
"time"
"github.com/google/uuid"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
)
// api version for the Keptn Metric CRDs
const (
apiVersion = "v1beta1"
groupName = "metrics.keptn.sh"
keptnMetricsResourceName = "keptnmetrics"
analysisResourceName = "analyses"
)
var keptnMetricsResource = schema.GroupVersionResource{
Group: groupName,
Version: apiVersion,
Resource: keptnMetricsResourceName,
}
var analysisResource = schema.GroupVersionResource{
Group: groupName,
Version: apiVersion,
Resource: analysisResourceName,
}
type queryObject struct {
GroupVersionResource schema.GroupVersionResource
ResourceName string
DurationString string
Namespace string
Arguments map[string]interface{}
}
type KeptnProvider struct {
client dynamic.Interface
analysisTimeout time.Duration
}
func NewKeptnProvider(cfg *rest.Config) (*KeptnProvider, error) {
if cfg == nil {
return nil, errors.New("could not initialize KeptnProvider: no KubeConfig provided")
}
client, err := dynamic.NewForConfig(cfg)
if err != nil {
return nil, fmt.Errorf("could not initialize KeptnProvider: %w", err)
}
return &KeptnProvider{
client: client,
analysisTimeout: 10 * time.Second,
}, nil
}
// RunQuery fetches the value of a KeptnMetric or Analysis,
// based on the selector provided in the query.
// The format of the selector is the following:
// <keptnmetric|analysis>/<namespace>/<resourceName>/<duration>/<arguments>
func (k *KeptnProvider) RunQuery(query string) (float64, error) {
queryObj, err := parseQuery(query)
if err != nil {
return 0, err
}
switch queryObj.GroupVersionResource.Resource {
case keptnMetricsResourceName:
return k.queryKeptnMetric(queryObj)
case analysisResourceName:
return k.queryKeptnAnalysis(queryObj)
default:
return 0, errors.New("unsupported query")
}
}
func (k *KeptnProvider) IsOnline() (bool, error) {
// TODO should we check for the keptn deployment to be up and running in the cluster?
return true, nil
}
func (k *KeptnProvider) queryKeptnMetric(queryObj *queryObject) (float64, error) {
get, err := k.client.Resource(queryObj.GroupVersionResource).
Namespace(queryObj.Namespace).
Get(
context.Background(),
queryObj.ResourceName,
v1.GetOptions{},
)
if err != nil {
return 0, fmt.Errorf("could not retrieve KeptnMetric %s/%s: %w", queryObj.Namespace, queryObj.ResourceName, err)
}
if status, ok := get.Object["status"]; ok {
if statusObj, ok := status.(map[string]interface{}); ok {
if value, ok := statusObj["value"].(string); ok {
floatValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return 0, fmt.Errorf("could not parse value of KeptnMetric %s/%s to float: %w", queryObj.Namespace, queryObj.ResourceName, err)
}
return floatValue, nil
}
}
}
return 0, fmt.Errorf("could not retrieve KeptnMetric - no value found in resource %s/%s", queryObj.Namespace, queryObj.ResourceName)
}
func (k *KeptnProvider) queryKeptnAnalysis(obj *queryObject) (float64, error) {
analysis := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": fmt.Sprintf("metrics.keptn.sh/%s", apiVersion),
"kind": "Analysis",
"metadata": map[string]interface{}{
"name": fmt.Sprintf("%s-%s", obj.ResourceName, uuid.New().String()[:6]),
"namespace": obj.Namespace,
},
"spec": map[string]interface{}{
"analysisDefinition": map[string]interface{}{
"name": obj.ResourceName,
},
"timeframe": map[string]interface{}{
"recent": obj.DurationString,
},
"args": obj.Arguments,
},
},
}
// set the timeout to 10s - this will give Keptn enough time to reconcile the Analysis
// and store the result in the status of the resource created here.
ctx, cancel := context.WithTimeout(context.Background(), k.analysisTimeout)
defer cancel()
createdAnalysis, err := k.client.
Resource(obj.GroupVersionResource).
Namespace(obj.Namespace).
Create(ctx, analysis, v1.CreateOptions{})
if err != nil {
return 0, fmt.Errorf("could not create Keptn Analysis %s/%s: %w", obj.Namespace, obj.ResourceName, err)
}
// delete the created analysis at the end of the function
defer func() {
err := k.client.
Resource(obj.GroupVersionResource).
Namespace(obj.Namespace).
Delete(
context.TODO(),
createdAnalysis.GetName(),
v1.DeleteOptions{},
)
if err != nil {
klog.Errorf("Could not delete Keptn Analysis '%s': %v", createdAnalysis.GetName(), err)
}
}()
for {
// retrieve the current state of the created Analysis resource every 1s, until
// it has been completed, and the evaluation result is available.
// We do this until the timeout of the context expires. If no result is available
// by then, we return an error.
select {
case <-ctx.Done():
return 0, fmt.Errorf("encountered timeout while waiting for Keptn Analysis %s/%s to be finished", obj.Namespace, obj.ResourceName)
case <-time.After(time.Second):
get, err := k.client.Resource(obj.GroupVersionResource).Namespace(obj.Namespace).Get(ctx, createdAnalysis.GetName(), v1.GetOptions{})
if err != nil {
return 0, fmt.Errorf("could not check status of created Keptn Analysis %s/%s: %w", obj.Namespace, obj.ResourceName, err)
}
statusStr, ok, err := unstructured.NestedString(get.Object, "status", "state")
if err != nil {
return 0, fmt.Errorf("could not check status of created Keptn Analysis %s/%s: %w", obj.Namespace, obj.ResourceName, err)
}
if ok && statusStr == "Completed" {
passed, ok, err := unstructured.NestedBool(get.Object, "status", "pass")
if err != nil {
return 0, fmt.Errorf("could not check status of created Keptn Analysis %s/%s: %w", obj.Namespace, obj.ResourceName, err)
}
if ok {
if passed {
return 1, nil
}
return 0, nil
}
}
}
}
}
func parseQuery(query string) (*queryObject, error) {
result := &queryObject{}
// sanitize the query by converting to lower case, trimming spaces and line break characters
split := strings.Split(
strings.TrimSpace(
strings.TrimSuffix(
strings.ToLower(query),
"\n",
),
),
"/",
)
if len(split) < 3 {
return nil, errors.New("unexpected query format. query must be in the format <keptnmetric|analysis>/<namespace>/<resourceName>/<duration>/<arguments>")
}
switch split[0] {
// take into account both singular and plural naming of resource names, to reduce probability of errors
case "keptnmetric", keptnMetricsResourceName:
result.GroupVersionResource = keptnMetricsResource
case "analysis", analysisResourceName:
result.GroupVersionResource = analysisResource
// add the duration for the Analysis, if available
if len(split) >= 4 {
result.DurationString = split[3]
} else {
//set to '1m' by default
result.DurationString = "1m"
}
// add arguments - these are provided as a comma separated list of key/value pairs
result.Arguments = map[string]interface{}{}
if len(split) >= 5 {
args := strings.Split(split[4], ";")
for i := 0; i < len(args); i++ {
keyValue := strings.Split(args[i], "=")
if len(keyValue) == 2 {
result.Arguments[keyValue[0]] = keyValue[1]
}
}
}
default:
return nil, errors.New("unexpected resource kind provided in the query. must be one of: ['keptnmetric', 'analysis']")
}
result.Namespace = split[1]
result.ResourceName = split[2]
return result, nil
}

View File

@@ -0,0 +1,381 @@
package providers
import (
"context"
"errors"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic/fake"
"k8s.io/client-go/rest"
)
func TestNewKeptnProvider(t *testing.T) {
provider, err := NewKeptnProvider(&rest.Config{})
require.Nil(t, err)
require.NotNil(t, provider)
isOnline, err := provider.IsOnline()
require.NoError(t, err)
require.True(t, isOnline)
}
func TestNewKeptnProvider_NoKubeConfig(t *testing.T) {
provider, err := NewKeptnProvider(nil)
require.Error(t, err)
require.Nil(t, provider)
}
func TestKeptnProvider_RunQuery_KeptnMetric(t *testing.T) {
tests := []struct {
name string
setupClient func() *fake.FakeDynamicClient
query string
want float64
wantErr bool
}{
{
name: "wrong query format",
setupClient: func() *fake.FakeDynamicClient {
fakeClient := fake.NewSimpleDynamicClient(
runtime.NewScheme(),
getSampleKeptnMetric("my-metric", "3.0"),
)
return fakeClient
},
query: "invalid/default",
want: 0,
wantErr: true,
},
{
name: "unsupported resource type",
setupClient: func() *fake.FakeDynamicClient {
fakeClient := fake.NewSimpleDynamicClient(
runtime.NewScheme(),
getSampleKeptnMetric("my-metric", "3.0"),
)
return fakeClient
},
query: "invalid/default/my-metric",
want: 0,
wantErr: true,
},
{
name: "get KeptnMetric value",
setupClient: func() *fake.FakeDynamicClient {
fakeClient := fake.NewSimpleDynamicClient(
runtime.NewScheme(),
getSampleKeptnMetric("my-metric", "3.0"),
)
return fakeClient
},
query: "keptnmetric/default/my-metric",
want: 3.0,
wantErr: false,
},
{
name: "KeptnMetric not found",
setupClient: func() *fake.FakeDynamicClient {
fakeClient := fake.NewSimpleDynamicClient(
runtime.NewScheme(),
)
return fakeClient
},
query: "keptnmetric/default/my-metric",
want: 0,
wantErr: true,
},
{
name: "KeptnMetric with invalid value",
setupClient: func() *fake.FakeDynamicClient {
fakeClient := fake.NewSimpleDynamicClient(
runtime.NewScheme(),
getSampleKeptnMetric("my-metric", "invalid"),
)
return fakeClient
},
query: "keptnmetric/default/my-metric",
want: 0,
wantErr: true,
},
{
name: "KeptnMetric with no value",
setupClient: func() *fake.FakeDynamicClient {
keptnMetric := getSampleKeptnMetric("my-metric", "")
data := keptnMetric.Object
delete(data, "status")
keptnMetric.SetUnstructuredContent(data)
fakeClient := fake.NewSimpleDynamicClient(
runtime.NewScheme(),
keptnMetric,
)
return fakeClient
},
query: "keptnmetric/default/my-metric",
want: 0,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
k := &KeptnProvider{
client: tt.setupClient(),
}
got, err := k.RunQuery(tt.query)
if tt.wantErr {
require.NotNil(t, err)
} else {
require.Nil(t, err)
}
require.Equalf(t, tt.want, got, "RunQuery(%v)", tt.query)
})
}
}
func TestKeptnProvider_RunQueryAnalysis(t *testing.T) {
tests := []struct {
name string
setupClient func() *fake.FakeDynamicClient
// verificationFunc() will run in a separate go routine
// and check if the expected resources are created
verificationFunc func(fakeClient *fake.FakeDynamicClient) error
query string
want float64
wantErr bool
}{
{
name: "get passed Analysis",
setupClient: func() *fake.FakeDynamicClient {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(analysisResource.GroupVersion())
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: analysisResource.Group, Version: analysisResource.Version, Kind: "AnalysisList"}, &unstructured.UnstructuredList{})
fakeClient := fake.NewSimpleDynamicClientWithCustomListKinds(
scheme,
map[schema.GroupVersionResource]string{
analysisResource: "AnalysisList",
},
)
return fakeClient
},
verificationFunc: func(fakeClient *fake.FakeDynamicClient) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
for {
select {
case <-ctx.Done():
return errors.New("timed out waiting for the condition")
case <-time.After(100 * time.Millisecond):
// verify the creation of the expected resource
list, err := fakeClient.Resource(analysisResource).
Namespace("default").
List(ctx, v1.ListOptions{
Limit: 1,
})
if err != nil || len(list.Items) == 0 {
continue
}
createdAnalysis := list.Items[0]
require.Equal(t, map[string]interface{}{
"analysisDefinition": map[string]interface{}{
"name": "my-analysis",
},
"args": map[string]interface{}{
"foo": "bar",
"bar": "foo",
},
"timeframe": map[string]interface{}{
"recent": "5m",
},
}, createdAnalysis.Object["spec"])
err = unstructured.SetNestedMap(
createdAnalysis.Object,
map[string]interface{}{
"state": "Completed",
"pass": true,
},
"status",
)
require.Nil(t, err)
_, err = fakeClient.Resource(analysisResource).Namespace("default").Update(ctx, &createdAnalysis, v1.UpdateOptions{})
require.Nil(t, err)
return nil
}
}
},
query: "analysis/default/my-analysis/5m/foo=bar;bar=foo",
want: 1,
wantErr: false,
},
{
name: "get failed Analysis",
setupClient: func() *fake.FakeDynamicClient {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(analysisResource.GroupVersion())
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: analysisResource.Group, Version: analysisResource.Version, Kind: "AnalysisList"}, &unstructured.UnstructuredList{})
fakeClient := fake.NewSimpleDynamicClientWithCustomListKinds(
scheme,
map[schema.GroupVersionResource]string{
analysisResource: "AnalysisList",
},
)
return fakeClient
},
verificationFunc: func(fakeClient *fake.FakeDynamicClient) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
for {
select {
case <-ctx.Done():
return errors.New("timed out waiting for the condition")
case <-time.After(10 * time.Millisecond):
// verify the creation of the expected resource
list, err := fakeClient.Resource(analysisResource).
Namespace("default").
List(ctx, v1.ListOptions{
Limit: 1,
})
if err != nil || len(list.Items) == 0 {
continue
}
createdAnalysis := list.Items[0]
require.Equal(t, map[string]interface{}{
"analysisDefinition": map[string]interface{}{
"name": "my-analysis",
},
"args": map[string]interface{}{},
"timeframe": map[string]interface{}{
"recent": "1m",
},
}, createdAnalysis.Object["spec"])
err = unstructured.SetNestedMap(
createdAnalysis.Object,
map[string]interface{}{
"state": "Completed",
"pass": false,
},
"status",
)
require.Nil(t, err)
_, err = fakeClient.Resource(analysisResource).Namespace("default").Update(ctx, &createdAnalysis, v1.UpdateOptions{})
require.Nil(t, err)
return nil
}
}
},
query: "analysis/default/my-analysis",
want: 0,
wantErr: false,
},
{
name: "analysis does not finish",
setupClient: func() *fake.FakeDynamicClient {
scheme := runtime.NewScheme()
scheme.AddKnownTypes(analysisResource.GroupVersion())
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: analysisResource.Group, Version: analysisResource.Version, Kind: "AnalysisList"}, &unstructured.UnstructuredList{})
fakeClient := fake.NewSimpleDynamicClientWithCustomListKinds(
scheme,
map[schema.GroupVersionResource]string{
analysisResource: "AnalysisList",
},
)
return fakeClient
},
verificationFunc: func(fakeClient *fake.FakeDynamicClient) error {
return nil
},
query: "analysis/default/my-analysis",
want: 0,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fakeClient := tt.setupClient()
k := &KeptnProvider{
client: fakeClient,
analysisTimeout: 1 * time.Second,
}
ctx := context.Background()
grp, ctx := errgroup.WithContext(ctx)
grp.Go(func() error {
return tt.verificationFunc(fakeClient)
})
got, err := k.RunQuery(tt.query)
if tt.wantErr {
require.NotNil(t, err)
} else {
require.Nil(t, err)
}
err = grp.Wait()
require.Nil(t, err)
require.Equalf(t, tt.want, got, "RunQuery(%v)", tt.query)
// verify that all created Analysis resources have been cleaned up
list, err := fakeClient.Resource(analysisResource).
Namespace("default").
List(ctx, v1.ListOptions{
Limit: 1,
})
require.NoError(t, err)
require.Empty(t, list.Items)
})
}
}
func getSampleKeptnMetric(metricName, value string) *unstructured.Unstructured {
keptnMetric := &unstructured.Unstructured{}
keptnMetric.SetUnstructuredContent(map[string]interface{}{
"apiVersion": fmt.Sprintf("metrics.keptn.sh/%s", apiVersion),
"kind": "KeptnMetric",
"metadata": map[string]interface{}{
"name": metricName,
"namespace": "default",
},
"spec": map[string]interface{}{
"fetchIntervalSeconds": "2",
"provider": map[string]interface{}{
"name": "my-provider",
},
"query": "my-query",
},
"status": map[string]interface{}{
"value": value,
},
})
return keptnMetric
}

View File

@@ -51,7 +51,8 @@ type prometheusResponse struct {
Metric struct {
Name string `json:"name"`
}
Value []interface{} `json:"value"`
Value []interface{} `json:"value"`
Values []interface{} `json:"values"`
}
}
}
@@ -147,6 +148,9 @@ func (p *PrometheusProvider) RunQuery(query string) (float64, error) {
var value *float64
for _, v := range result.Data.Result {
if v.Values != nil {
return 0, fmt.Errorf("%w", ErrMultipleValuesReturned)
}
metricValue := v.Value[1]
switch metricValue.(type) {
case string:

View File

@@ -180,6 +180,39 @@ func TestPrometheusProvider_RunQueryWithBasicAuth(t *testing.T) {
})
}
multipleResultTests := []struct {
name string
queryResult string
}{
{name: "values instead of value", queryResult: `{"status": "success","data": {"resultType": "matrix","result": [{"metric": {"__name__": "processTime_seconds:avg"},"values": [[1714404069.294,"NaN"],[1714404071.3,"NaN"],[1714404099.294,"NaN"],[1714404101.3,"NaN"]]},{"metric": {"__name__": "processTime_seconds:avg"},"values": [[1714404069.294,"NaN"],[1714404071.3,"NaN"],[1714404099.294,"NaN"],[1714404101.3,"NaN"]]}]}}`},
}
for _, tt := range multipleResultTests {
t.Run(tt.name, func(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
json := tt.queryResult
w.Write([]byte(json))
}))
defer ts.Close()
clients := prometheusFake()
template, err := clients.flaggerClient.FlaggerV1beta1().
MetricTemplates("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
template.Spec.Provider.Address = ts.URL
secret, err := clients.kubeClient.CoreV1().Secrets("default").Get(context.TODO(), "prometheus", metav1.GetOptions{})
require.NoError(t, err)
prom, err := NewPrometheusProvider(template.Spec.Provider, secret.Data)
require.NoError(t, err)
_, err = prom.RunQuery(template.Spec.Query)
require.True(t, errors.Is(err, ErrMultipleValuesReturned))
})
}
}
func TestPrometheusProvider_RunQueryWithBearerAuth(t *testing.T) {

View File

@@ -20,12 +20,13 @@ import (
"context"
"fmt"
"reflect"
"slices"
"strings"
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
v1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1"
"github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
"github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
@@ -532,7 +533,7 @@ func (gwr *GatewayAPIRouter) getSessionAffinityRouteRules(canary *flaggerv1.Cana
return []v1.HTTPRouteRule{stickyRouteRule, *weightedRouteRule}, nil
}
func (gwr *GatewayAPIRouter) mapRouteMatches(requestMatches []v1alpha3.HTTPMatchRequest) ([]v1.HTTPRouteMatch, error) {
func (gwr *GatewayAPIRouter) mapRouteMatches(requestMatches []istiov1beta1.HTTPMatchRequest) ([]v1.HTTPRouteMatch, error) {
matches := []v1.HTTPRouteMatch{}
for _, requestMatch := range requestMatches {
@@ -647,10 +648,23 @@ func (gwr *GatewayAPIRouter) mergeMatchConditions(analysis, service []v1.HTTPRou
return merged
}
func sortFiltersV1(headers []v1.HTTPHeader) {
if headers != nil {
slices.SortFunc(headers, func(a, b v1.HTTPHeader) int {
if a.Name == b.Name {
return strings.Compare(a.Value, b.Value)
}
return strings.Compare(string(a.Name), string(b.Name))
})
}
}
func (gwr *GatewayAPIRouter) makeFilters(canary *flaggerv1.Canary) []v1.HTTPRouteFilter {
var filters []v1.HTTPRouteFilter
if canary.Spec.Service.Headers != nil {
if canary.Spec.Service.Headers.Request != nil {
requestHeaderFilter := v1.HTTPRouteFilter{
Type: v1.HTTPRouteFilterRequestHeaderModifier,
@@ -663,6 +677,7 @@ func (gwr *GatewayAPIRouter) makeFilters(canary *flaggerv1.Canary) []v1.HTTPRout
Value: val,
})
}
sortFiltersV1(requestHeaderFilter.RequestHeaderModifier.Add)
for name, val := range canary.Spec.Service.Headers.Request.Set {
requestHeaderFilter.RequestHeaderModifier.Set = append(requestHeaderFilter.RequestHeaderModifier.Set, v1.HTTPHeader{
Name: v1.HTTPHeaderName(name),
@@ -670,6 +685,7 @@ func (gwr *GatewayAPIRouter) makeFilters(canary *flaggerv1.Canary) []v1.HTTPRout
})
}
sortFiltersV1(requestHeaderFilter.RequestHeaderModifier.Set)
for _, name := range canary.Spec.Service.Headers.Request.Remove {
requestHeaderFilter.RequestHeaderModifier.Remove = append(requestHeaderFilter.RequestHeaderModifier.Remove, name)
}
@@ -688,12 +704,14 @@ func (gwr *GatewayAPIRouter) makeFilters(canary *flaggerv1.Canary) []v1.HTTPRout
Value: val,
})
}
sortFiltersV1(responseHeaderFilter.ResponseHeaderModifier.Add)
for name, val := range canary.Spec.Service.Headers.Response.Set {
responseHeaderFilter.ResponseHeaderModifier.Set = append(responseHeaderFilter.ResponseHeaderModifier.Set, v1.HTTPHeader{
Name: v1.HTTPHeaderName(name),
Value: val,
})
}
sortFiltersV1(responseHeaderFilter.ResponseHeaderModifier.Set)
for _, name := range canary.Spec.Service.Headers.Response.Remove {
responseHeaderFilter.ResponseHeaderModifier.Remove = append(responseHeaderFilter.ResponseHeaderModifier.Remove, name)

View File

@@ -24,7 +24,9 @@ import (
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
v1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -352,3 +354,40 @@ func TestGatewayAPIRouter_getSessionAffinityRouteRules(t *testing.T) {
assert.Equal(t, string(headerModifier.Add[0].Name), setCookieHeader)
assert.Equal(t, headerModifier.Add[0].Value, fmt.Sprintf("%s; %s=%d", canary.Status.PreviousSessionAffinityCookie, maxAgeAttr, -1))
}
func TestGatewayAPIRouter_makeFilters(t *testing.T) {
canary := newTestGatewayAPICanary()
mocks := newFixture(canary)
canary.Spec.Service.Headers = &istiov1beta1.Headers{
Response: &istiov1beta1.HeaderOperations{
Set: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
Add: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
},
Request: &istiov1beta1.HeaderOperations{
Set: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
Add: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
},
}
router := &GatewayAPIRouter{
gatewayAPIClient: mocks.meshClient,
kubeClient: mocks.kubeClient,
logger: mocks.logger,
}
ignoreCmpOptions := []cmp.Option{
cmpopts.IgnoreFields(v1.BackendRef{}, "Weight"),
cmpopts.EquateEmpty(),
}
filters := router.makeFilters(canary)
for i := 0; i < 10; i++ {
newFilters := router.makeFilters(canary)
filtersDiff := cmp.Diff(
filters, newFilters,
ignoreCmpOptions...,
)
assert.Equal(t, "", filtersDiff)
}
}

View File

@@ -20,11 +20,12 @@ import (
"context"
"fmt"
"reflect"
"slices"
"strings"
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
"github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
"github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
@@ -493,7 +494,7 @@ func (gwr *GatewayAPIV1Beta1Router) getSessionAffinityRouteRules(canary *flagger
return []v1beta1.HTTPRouteRule{stickyRouteRule, *weightedRouteRule}, nil
}
func (gwr *GatewayAPIV1Beta1Router) mapRouteMatches(requestMatches []v1alpha3.HTTPMatchRequest) ([]v1beta1.HTTPRouteMatch, error) {
func (gwr *GatewayAPIV1Beta1Router) mapRouteMatches(requestMatches []istiov1beta1.HTTPMatchRequest) ([]v1beta1.HTTPRouteMatch, error) {
matches := []v1beta1.HTTPRouteMatch{}
for _, requestMatch := range requestMatches {
@@ -608,6 +609,18 @@ func (gwr *GatewayAPIV1Beta1Router) mergeMatchConditions(analysis, service []v1b
return merged
}
func sortFiltersV1beta1(headers []v1beta1.HTTPHeader) {
if headers != nil {
slices.SortFunc(headers, func(a, b v1beta1.HTTPHeader) int {
if a.Name == b.Name {
return strings.Compare(a.Value, b.Value)
}
return strings.Compare(string(a.Name), string(b.Name))
})
}
}
func (gwr *GatewayAPIV1Beta1Router) makeFilters(canary *flaggerv1.Canary) []v1beta1.HTTPRouteFilter {
var filters []v1beta1.HTTPRouteFilter
@@ -624,12 +637,14 @@ func (gwr *GatewayAPIV1Beta1Router) makeFilters(canary *flaggerv1.Canary) []v1be
Value: val,
})
}
sortFiltersV1beta1(requestHeaderFilter.RequestHeaderModifier.Add)
for name, val := range canary.Spec.Service.Headers.Request.Set {
requestHeaderFilter.RequestHeaderModifier.Set = append(requestHeaderFilter.RequestHeaderModifier.Set, v1beta1.HTTPHeader{
Name: v1beta1.HTTPHeaderName(name),
Value: val,
})
}
sortFiltersV1beta1(requestHeaderFilter.RequestHeaderModifier.Set)
for _, name := range canary.Spec.Service.Headers.Request.Remove {
requestHeaderFilter.RequestHeaderModifier.Remove = append(requestHeaderFilter.RequestHeaderModifier.Remove, name)
@@ -649,12 +664,14 @@ func (gwr *GatewayAPIV1Beta1Router) makeFilters(canary *flaggerv1.Canary) []v1be
Value: val,
})
}
sortFiltersV1beta1(responseHeaderFilter.ResponseHeaderModifier.Add)
for name, val := range canary.Spec.Service.Headers.Response.Set {
responseHeaderFilter.ResponseHeaderModifier.Set = append(responseHeaderFilter.ResponseHeaderModifier.Set, v1beta1.HTTPHeader{
Name: v1beta1.HTTPHeaderName(name),
Value: val,
})
}
sortFiltersV1beta1(responseHeaderFilter.ResponseHeaderModifier.Set)
for _, name := range canary.Spec.Service.Headers.Response.Remove {
responseHeaderFilter.ResponseHeaderModifier.Remove = append(responseHeaderFilter.ResponseHeaderModifier.Remove, name)

View File

@@ -23,8 +23,11 @@ import (
"testing"
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
v1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1"
"github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -349,3 +352,40 @@ func TestGatewayAPIV1Beta1Router_getSessionAffinityRouteRules(t *testing.T) {
assert.Equal(t, string(headerModifier.Add[0].Name), setCookieHeader)
assert.Equal(t, headerModifier.Add[0].Value, fmt.Sprintf("%s; %s=%d", canary.Status.PreviousSessionAffinityCookie, maxAgeAttr, -1))
}
func TestGatewayAPIV1Beta1Router_makeFilters(t *testing.T) {
canary := newTestGatewayAPICanary()
mocks := newFixture(canary)
canary.Spec.Service.Headers = &istiov1beta1.Headers{
Response: &istiov1beta1.HeaderOperations{
Set: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
Add: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
},
Request: &istiov1beta1.HeaderOperations{
Set: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
Add: map[string]string{"h1": "v1", "h2": "v2", "h3": "v3"},
},
}
router := &GatewayAPIV1Beta1Router{
gatewayAPIClient: mocks.meshClient,
kubeClient: mocks.kubeClient,
logger: mocks.logger,
}
ignoreCmpOptions := []cmp.Option{
cmpopts.IgnoreFields(v1.BackendRef{}, "Weight"),
cmpopts.EquateEmpty(),
}
filters := router.makeFilters(canary)
for i := 0; i < 10; i++ {
newFilters := router.makeFilters(canary)
filtersDiff := cmp.Diff(
filters, newFilters,
ignoreCmpOptions...,
)
assert.Equal(t, "", filtersDiff)
}
}

View File

@@ -18,6 +18,7 @@ package router
import (
"context"
"encoding/json"
"fmt"
corev1 "k8s.io/api/core/v1"
@@ -30,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
@@ -275,7 +277,8 @@ func (gr *GlooRouter) createFlaggerUpstream(canary *flaggerv1.Canary, upstreamNa
if err != nil {
return fmt.Errorf("service %s.%s get query error: %w", svcName, canary.Namespace, err)
}
_, err = upstreamClient.Get(context.TODO(), upstreamName, metav1.GetOptions{})
curUpstream, err := upstreamClient.Get(context.TODO(), upstreamName, metav1.GetOptions{})
if errors.IsNotFound(err) {
glooUpstreamWithConfig, err := gr.getGlooConfigUpstream(canary)
if err != nil {
@@ -288,10 +291,45 @@ func (gr *GlooRouter) createFlaggerUpstream(canary *flaggerv1.Canary, upstreamNa
}
} else if err != nil {
return fmt.Errorf("upstream %s.%s get query error: %w", upstreamName, canary.Namespace, err)
} else {
return gr.syncUpstreamSpec(curUpstream, canary)
}
return nil
}
func (gr *GlooRouter) syncUpstreamSpec(curUpstream *gloov1.Upstream, canary *flaggerv1.Canary) error {
glooUpstreamWithConfig, err := gr.getGlooConfigUpstream(canary)
if err != nil {
return err
}
if glooUpstreamWithConfig == nil {
return nil
}
glooUpstreamLB := glooUpstreamWithConfig.Spec.LoadBalancerConfig
loadBalancerDiff := cmp.Diff(glooUpstreamLB, curUpstream.Spec.LoadBalancerConfig)
if loadBalancerDiff != "" {
gr.logger.Debugf("detect diff in upstream spec %s.%s %s", curUpstream.Name, canary.Namespace, loadBalancerDiff)
patchUpstream := gloov1.Upstream{}
patchUpstream.Spec = gloov1.UpstreamSpec{}
patchUpstream.Spec.LoadBalancerConfig = glooUpstreamLB
patchBytes, err := json.Marshal(patchUpstream)
if err != nil {
return fmt.Errorf("unable to marshal patch upstream from %s.%s with error: %w", glooUpstreamWithConfig.Name, glooUpstreamWithConfig.Namespace, err)
}
_, err = gr.glooClient.GlooV1().Upstreams(canary.Namespace).Patch(context.TODO(), curUpstream.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{})
if err != nil {
return fmt.Errorf("upstream %s.%s spec patch error: %w", curUpstream.Name, canary.Namespace, err)
}
}
return nil
}
func (gr *GlooRouter) getGlooUpstreamKubeService(canary *flaggerv1.Canary, svc *corev1.Service, upstreamName string, glooUpstreamWithConfig *gloov1.Upstream) *gloov1.Upstream {
upstreamSpec := gloov1.UpstreamSpec{}

View File

@@ -27,7 +27,7 @@ import (
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
istiov1alpha1 "github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
)
func TestIngressRouter_Reconcile(t *testing.T) {
@@ -116,7 +116,7 @@ func TestIngressRouter_ABTest(t *testing.T) {
{
makeCanary: func() *flaggerv1.Canary {
mocks.ingressCanary.Spec.Analysis.Iterations = 1
mocks.ingressCanary.Spec.Analysis.Match = []istiov1alpha3.HTTPMatchRequest{
mocks.ingressCanary.Spec.Analysis.Match = []istiov1beta1.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"x-user-type": {
@@ -133,7 +133,7 @@ func TestIngressRouter_ABTest(t *testing.T) {
{
makeCanary: func() *flaggerv1.Canary {
mocks.ingressCanary.Spec.Analysis.Iterations = 1
mocks.ingressCanary.Spec.Analysis.Match = []istiov1alpha3.HTTPMatchRequest{
mocks.ingressCanary.Spec.Analysis.Match = []istiov1beta1.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"x-user-type": {
@@ -150,7 +150,7 @@ func TestIngressRouter_ABTest(t *testing.T) {
{
makeCanary: func() *flaggerv1.Canary {
mocks.ingressCanary.Spec.Analysis.Iterations = 1
mocks.ingressCanary.Spec.Analysis.Match = []istiov1alpha3.HTTPMatchRequest{
mocks.ingressCanary.Spec.Analysis.Match = []istiov1beta1.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"cookie": {

View File

@@ -34,7 +34,7 @@ import (
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
istiov1alpha1 "github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
)
@@ -73,15 +73,15 @@ func (ir *IstioRouter) Reconcile(canary *flaggerv1.Canary) error {
}
func (ir *IstioRouter) reconcileDestinationRule(canary *flaggerv1.Canary, name string) error {
newSpec := istiov1alpha3.DestinationRuleSpec{
newSpec := istiov1beta1.DestinationRuleSpec{
Host: name,
TrafficPolicy: canary.Spec.Service.TrafficPolicy,
}
destinationRule, err := ir.istioClient.NetworkingV1alpha3().DestinationRules(canary.Namespace).Get(context.TODO(), name, metav1.GetOptions{})
destinationRule, err := ir.istioClient.NetworkingV1beta1().DestinationRules(canary.Namespace).Get(context.TODO(), name, metav1.GetOptions{})
// insert
if errors.IsNotFound(err) {
destinationRule = &istiov1alpha3.DestinationRule{
destinationRule = &istiov1beta1.DestinationRule{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: canary.Namespace,
@@ -97,7 +97,7 @@ func (ir *IstioRouter) reconcileDestinationRule(canary *flaggerv1.Canary, name s
}),
}
}
_, err = ir.istioClient.NetworkingV1alpha3().DestinationRules(canary.Namespace).Create(context.TODO(), destinationRule, metav1.CreateOptions{})
_, err = ir.istioClient.NetworkingV1beta1().DestinationRules(canary.Namespace).Create(context.TODO(), destinationRule, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("DestinationRule %s.%s create error: %w", name, canary.Namespace, err)
}
@@ -113,7 +113,7 @@ func (ir *IstioRouter) reconcileDestinationRule(canary *flaggerv1.Canary, name s
if diff := cmp.Diff(newSpec, destinationRule.Spec); diff != "" {
clone := destinationRule.DeepCopy()
clone.Spec = newSpec
_, err = ir.istioClient.NetworkingV1alpha3().DestinationRules(canary.Namespace).Update(context.TODO(), clone, metav1.UpdateOptions{})
_, err = ir.istioClient.NetworkingV1beta1().DestinationRules(canary.Namespace).Update(context.TODO(), clone, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("DestinationRule %s.%s update error: %w", name, canary.Namespace, err)
}
@@ -131,10 +131,10 @@ func isTcp(canary *flaggerv1.Canary) bool {
}
// map canary.spec.service.match into L4Match
func canaryToL4Match(canary *flaggerv1.Canary) []istiov1alpha3.L4MatchAttributes {
var match []istiov1alpha3.L4MatchAttributes
func canaryToL4Match(canary *flaggerv1.Canary) []istiov1beta1.L4MatchAttributes {
var match []istiov1beta1.L4MatchAttributes
for _, m := range canary.Spec.Service.Match {
match = append(match, istiov1alpha3.L4MatchAttributes{
match = append(match, istiov1beta1.L4MatchAttributes{
Port: int(m.Port),
})
}
@@ -181,7 +181,7 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
}
// create destinations with primary weight 100% and canary weight 0%
canaryRoute := []istiov1alpha3.HTTPRouteDestination{
canaryRoute := []istiov1beta1.HTTPRouteDestination{
makeDestination(canary, primaryName, 100),
makeDestination(canary, canaryName, 0),
}
@@ -192,13 +192,13 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
gateways = []string{}
}
var newSpec istiov1alpha3.VirtualServiceSpec
var newSpec istiov1beta1.VirtualServiceSpec
if isTcp(canary) {
newSpec = istiov1alpha3.VirtualServiceSpec{
newSpec = istiov1beta1.VirtualServiceSpec{
Hosts: hosts,
Gateways: gateways,
Tcp: []istiov1alpha3.TCPRoute{
Tcp: []istiov1beta1.TCPRoute{
{
Match: canaryToL4Match(canary),
Route: canaryRoute,
@@ -206,10 +206,10 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
},
}
} else {
newSpec = istiov1alpha3.VirtualServiceSpec{
newSpec = istiov1beta1.VirtualServiceSpec{
Hosts: hosts,
Gateways: gateways,
Http: []istiov1alpha3.HTTPRoute{
Http: []istiov1beta1.HTTPRoute{
{
Match: canary.Spec.Service.Match,
Rewrite: canary.Spec.Service.GetIstioRewrite(),
@@ -237,7 +237,7 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
if !isTcp(canary) && len(canary.GetAnalysis().Match) > 0 {
canaryMatch := mergeMatchConditions(canary.GetAnalysis().Match, canary.Spec.Service.Match)
newSpec.Http = []istiov1alpha3.HTTPRoute{
newSpec.Http = []istiov1beta1.HTTPRoute{
{
Match: canaryMatch,
Rewrite: canary.Spec.Service.GetIstioRewrite(),
@@ -254,17 +254,17 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
Retries: canary.Spec.Service.Retries,
CorsPolicy: canary.Spec.Service.CorsPolicy,
Headers: canary.Spec.Service.Headers,
Route: []istiov1alpha3.HTTPRouteDestination{
Route: []istiov1beta1.HTTPRouteDestination{
makeDestination(canary, primaryName, 100),
},
},
}
}
virtualService, err := ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
virtualService, err := ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
// insert
if errors.IsNotFound(err) {
virtualService = &istiov1alpha3.VirtualService{
virtualService = &istiov1beta1.VirtualService{
ObjectMeta: metav1.ObjectMeta{
Name: apexName,
Namespace: canary.Namespace,
@@ -282,7 +282,7 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
}),
}
}
_, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Create(context.TODO(), virtualService, metav1.CreateOptions{})
_, err = ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Create(context.TODO(), virtualService, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("VirtualService %s.%s create error: %w", apexName, canary.Namespace, err)
}
@@ -300,20 +300,20 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
}
ignoreCmpOptions := []cmp.Option{
cmpopts.IgnoreFields(istiov1alpha3.HTTPRouteDestination{}, "Weight"),
cmpopts.IgnoreFields(istiov1alpha3.HTTPRoute{}, "Mirror", "MirrorPercentage"),
cmpopts.IgnoreFields(istiov1beta1.HTTPRouteDestination{}, "Weight"),
cmpopts.IgnoreFields(istiov1beta1.HTTPRoute{}, "Mirror", "MirrorPercentage"),
}
if canary.Spec.Analysis.SessionAffinity != nil {
// We ignore this route as this does not do weighted routing and is handled exclusively
// by SetRoutes().
ignoreSlice := cmpopts.IgnoreSliceElements(func(t istiov1alpha3.HTTPRoute) bool {
ignoreSlice := cmpopts.IgnoreSliceElements(func(t istiov1beta1.HTTPRoute) bool {
if t.Name == stickyRouteName {
return true
}
return false
})
ignoreCmpOptions = append(ignoreCmpOptions, ignoreSlice)
ignoreCmpOptions = append(ignoreCmpOptions, cmpopts.IgnoreFields(istiov1alpha3.HTTPRouteDestination{}, "Headers"))
ignoreCmpOptions = append(ignoreCmpOptions, cmpopts.IgnoreFields(istiov1beta1.HTTPRouteDestination{}, "Headers"))
}
if v, ok := virtualService.Annotations[kubectlAnnotation]; ok {
newMetadata.Annotations[kubectlAnnotation] = v
@@ -354,7 +354,7 @@ func (ir *IstioRouter) reconcileVirtualService(canary *flaggerv1.Canary) error {
vtClone.ObjectMeta.Annotations[configAnnotation] = string(b)
}
_, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Update(context.TODO(), vtClone, metav1.UpdateOptions{})
_, err = ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Update(context.TODO(), vtClone, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("VirtualService %s.%s update error: %w", apexName, canary.Namespace, err)
}
@@ -374,8 +374,8 @@ func (ir *IstioRouter) GetRoutes(canary *flaggerv1.Canary) (
err error,
) {
apexName, primaryName, canaryName := canary.GetServiceNames()
vs := &istiov1alpha3.VirtualService{}
vs, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
vs := &istiov1beta1.VirtualService{}
vs, err = ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
if err != nil {
err = fmt.Errorf("VirtualService %s.%s get query error %v", apexName, canary.Namespace, err)
return
@@ -383,7 +383,7 @@ func (ir *IstioRouter) GetRoutes(canary *flaggerv1.Canary) (
if isTcp(canary) {
ir.logger.Infof("Canary %s.%s uses TCP service", canary.Name, canary.Namespace)
var tcpRoute istiov1alpha3.TCPRoute
var tcpRoute istiov1beta1.TCPRoute
for _, tcp := range vs.Spec.Tcp {
for _, r := range tcp.Route {
if r.Destination.Host == canaryName {
@@ -413,7 +413,7 @@ func (ir *IstioRouter) GetRoutes(canary *flaggerv1.Canary) (
ir.logger.Infof("Canary %s.%s uses HTTP service", canary.Name, canary.Namespace)
var httpRoute istiov1alpha3.HTTPRoute
var httpRoute istiov1beta1.HTTPRoute
for _, http := range vs.Spec.Http {
for _, r := range http.Route {
if r.Destination.Host == canaryName {
@@ -469,7 +469,7 @@ func (ir *IstioRouter) SetRoutes(
) error {
apexName, primaryName, canaryName := canary.GetServiceNames()
vs, err := ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
vs, err := ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("VirtualService %s.%s get query error %v", apexName, canary.Namespace, err)
}
@@ -478,18 +478,18 @@ func (ir *IstioRouter) SetRoutes(
if isTcp(canary) {
// weighted routing (progressive canary)
weightedRoute := istiov1alpha3.TCPRoute{
weightedRoute := istiov1beta1.TCPRoute{
Match: canaryToL4Match(canary),
Route: []istiov1alpha3.HTTPRouteDestination{
Route: []istiov1beta1.HTTPRouteDestination{
makeDestination(canary, primaryName, primaryWeight),
makeDestination(canary, canaryName, canaryWeight),
},
}
vsCopy.Spec.Tcp = []istiov1alpha3.TCPRoute{
vsCopy.Spec.Tcp = []istiov1beta1.TCPRoute{
weightedRoute,
}
vs, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Update(context.TODO(), vsCopy, metav1.UpdateOptions{})
vs, err = ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Update(context.TODO(), vsCopy, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("VirtualService %s.%s update failed: %w", apexName, canary.Namespace, err)
}
@@ -497,19 +497,19 @@ func (ir *IstioRouter) SetRoutes(
}
// weighted routing (progressive canary)
weightedRoute := istiov1alpha3.HTTPRoute{
weightedRoute := istiov1beta1.HTTPRoute{
Match: canary.Spec.Service.Match,
Rewrite: canary.Spec.Service.GetIstioRewrite(),
Timeout: canary.Spec.Service.Timeout,
Retries: canary.Spec.Service.Retries,
CorsPolicy: canary.Spec.Service.CorsPolicy,
Headers: canary.Spec.Service.Headers,
Route: []istiov1alpha3.HTTPRouteDestination{
Route: []istiov1beta1.HTTPRouteDestination{
makeDestination(canary, primaryName, primaryWeight),
makeDestination(canary, canaryName, canaryWeight),
},
}
vsCopy.Spec.Http = []istiov1alpha3.HTTPRoute{
vsCopy.Spec.Http = []istiov1beta1.HTTPRoute{
weightedRoute,
}
@@ -527,8 +527,8 @@ func (ir *IstioRouter) SetRoutes(
for i, routeDest := range weightedRoute.Route {
if routeDest.Destination.Host == canaryName {
if routeDest.Headers == nil {
routeDest.Headers = &istiov1alpha3.Headers{
Response: &istiov1alpha3.HeaderOperations{},
routeDest.Headers = &istiov1beta1.Headers{
Response: &istiov1beta1.HeaderOperations{},
}
}
routeDest.Headers.Response.Add = map[string]string{
@@ -541,16 +541,16 @@ func (ir *IstioRouter) SetRoutes(
}
cookieKeyAndVal := strings.Split(canary.Status.SessionAffinityCookie, "=")
cookieMatch := istiov1alpha3.HTTPMatchRequest{
cookieMatch := istiov1beta1.HTTPMatchRequest{
Headers: map[string]istiov1alpha1.StringMatch{
cookieHeader: {
Regex: fmt.Sprintf(".*%s.*%s.*", cookieKeyAndVal[0], cookieKeyAndVal[1]),
},
},
}
canaryMatch := mergeMatchConditions([]istiov1alpha3.HTTPMatchRequest{cookieMatch}, canary.Spec.Service.Match)
canaryMatch := mergeMatchConditions([]istiov1beta1.HTTPMatchRequest{cookieMatch}, canary.Spec.Service.Match)
stickyRoute.Match = canaryMatch
stickyRoute.Route = []istiov1alpha3.HTTPRouteDestination{
stickyRoute.Route = []istiov1beta1.HTTPRouteDestination{
makeDestination(canary, primaryName, 0),
makeDestination(canary, canaryName, 100),
}
@@ -564,24 +564,24 @@ func (ir *IstioRouter) SetRoutes(
// Match against the previous session cookie and delete that cookie
if previousCookie != "" {
cookieKeyAndVal := strings.Split(previousCookie, "=")
cookieMatch := istiov1alpha3.HTTPMatchRequest{
cookieMatch := istiov1beta1.HTTPMatchRequest{
Headers: map[string]istiov1alpha1.StringMatch{
cookieHeader: {
Regex: fmt.Sprintf(".*%s.*%s.*", cookieKeyAndVal[0], cookieKeyAndVal[1]),
},
},
}
canaryMatch := mergeMatchConditions([]istiov1alpha3.HTTPMatchRequest{cookieMatch}, canary.Spec.Service.Match)
canaryMatch := mergeMatchConditions([]istiov1beta1.HTTPMatchRequest{cookieMatch}, canary.Spec.Service.Match)
stickyRoute.Match = canaryMatch
if stickyRoute.Headers == nil {
stickyRoute.Headers = &istiov1alpha3.Headers{
Response: &istiov1alpha3.HeaderOperations{
stickyRoute.Headers = &istiov1beta1.Headers{
Response: &istiov1beta1.HeaderOperations{
Add: map[string]string{},
},
}
} else if stickyRoute.Headers.Response == nil {
stickyRoute.Headers.Response = &istiov1alpha3.HeaderOperations{
stickyRoute.Headers.Response = &istiov1beta1.HeaderOperations{
Add: map[string]string{},
}
} else if stickyRoute.Headers.Response.Add == nil {
@@ -592,18 +592,18 @@ func (ir *IstioRouter) SetRoutes(
canary.Status.SessionAffinityCookie = ""
}
vsCopy.Spec.Http = []istiov1alpha3.HTTPRoute{
vsCopy.Spec.Http = []istiov1beta1.HTTPRoute{
stickyRoute, weightedRoute,
}
}
if mirrored {
vsCopy.Spec.Http[0].Mirror = &istiov1alpha3.Destination{
vsCopy.Spec.Http[0].Mirror = &istiov1beta1.Destination{
Host: canaryName,
}
if mw := canary.GetAnalysis().MirrorWeight; mw > 0 {
vsCopy.Spec.Http[0].MirrorPercentage = &istiov1alpha3.Percent{Value: float64(mw)}
vsCopy.Spec.Http[0].MirrorPercentage = &istiov1beta1.Percent{Value: float64(mw)}
}
}
@@ -611,7 +611,7 @@ func (ir *IstioRouter) SetRoutes(
if len(canary.GetAnalysis().Match) > 0 {
// merge the common routes with the canary ones
canaryMatch := mergeMatchConditions(canary.GetAnalysis().Match, canary.Spec.Service.Match)
vsCopy.Spec.Http = []istiov1alpha3.HTTPRoute{
vsCopy.Spec.Http = []istiov1beta1.HTTPRoute{
{
Match: canaryMatch,
Rewrite: canary.Spec.Service.GetIstioRewrite(),
@@ -619,7 +619,7 @@ func (ir *IstioRouter) SetRoutes(
Retries: canary.Spec.Service.Retries,
CorsPolicy: canary.Spec.Service.CorsPolicy,
Headers: canary.Spec.Service.Headers,
Route: []istiov1alpha3.HTTPRouteDestination{
Route: []istiov1beta1.HTTPRouteDestination{
makeDestination(canary, primaryName, primaryWeight),
makeDestination(canary, canaryName, canaryWeight),
},
@@ -631,14 +631,14 @@ func (ir *IstioRouter) SetRoutes(
Retries: canary.Spec.Service.Retries,
CorsPolicy: canary.Spec.Service.CorsPolicy,
Headers: canary.Spec.Service.Headers,
Route: []istiov1alpha3.HTTPRouteDestination{
Route: []istiov1beta1.HTTPRouteDestination{
makeDestination(canary, primaryName, primaryWeight),
},
},
}
}
vs, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Update(context.TODO(), vsCopy, metav1.UpdateOptions{})
vs, err = ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Update(context.TODO(), vsCopy, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("VirtualService %s.%s update failed: %w", apexName, canary.Namespace, err)
}
@@ -649,14 +649,14 @@ func (ir *IstioRouter) Finalize(canary *flaggerv1.Canary) error {
// Need to see if I can get the annotation orig-configuration
apexName, _, _ := canary.GetServiceNames()
vs, err := ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
vs, err := ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Get(context.TODO(), apexName, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("VirtualService %s.%s get query error: %w", apexName, canary.Namespace, err)
}
var storedSpec istiov1alpha3.VirtualServiceSpec
var storedSpec istiov1beta1.VirtualServiceSpec
if a, ok := vs.ObjectMeta.Annotations[kubectlAnnotation]; ok {
var storedVS istiov1alpha3.VirtualService
var storedVS istiov1beta1.VirtualService
if err := json.Unmarshal([]byte(a), &storedVS); err != nil {
return fmt.Errorf("VirtualService %s.%s failed to unMarshal annotation %s",
apexName, canary.Namespace, kubectlAnnotation)
@@ -675,7 +675,7 @@ func (ir *IstioRouter) Finalize(canary *flaggerv1.Canary) error {
clone := vs.DeepCopy()
clone.Spec = storedSpec
_, err = ir.istioClient.NetworkingV1alpha3().VirtualServices(canary.Namespace).Update(context.TODO(), clone, metav1.UpdateOptions{})
_, err = ir.istioClient.NetworkingV1beta1().VirtualServices(canary.Namespace).Update(context.TODO(), clone, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("VirtualService %s.%s update error: %w", apexName, canary.Namespace, err)
}
@@ -683,12 +683,12 @@ func (ir *IstioRouter) Finalize(canary *flaggerv1.Canary) error {
}
// mergeMatchConditions appends the URI match rules to canary conditions
func mergeMatchConditions(canary, defaults []istiov1alpha3.HTTPMatchRequest) []istiov1alpha3.HTTPMatchRequest {
func mergeMatchConditions(canary, defaults []istiov1beta1.HTTPMatchRequest) []istiov1beta1.HTTPMatchRequest {
if len(defaults) == 0 {
return canary
}
merged := make([]istiov1alpha3.HTTPMatchRequest, len(canary)*len(defaults))
merged := make([]istiov1beta1.HTTPMatchRequest, len(canary)*len(defaults))
num := 0
for _, c := range canary {
for _, d := range defaults {
@@ -707,9 +707,9 @@ func mergeMatchConditions(canary, defaults []istiov1alpha3.HTTPMatchRequest) []i
}
// makeDestination returns a an destination weight for the specified host
func makeDestination(canary *flaggerv1.Canary, host string, weight int) istiov1alpha3.HTTPRouteDestination {
dest := istiov1alpha3.HTTPRouteDestination{
Destination: istiov1alpha3.Destination{
func makeDestination(canary *flaggerv1.Canary, host string, weight int) istiov1beta1.HTTPRouteDestination {
dest := istiov1beta1.HTTPRouteDestination{
Destination: istiov1beta1.Destination{
Host: host,
},
Weight: weight,
@@ -719,10 +719,10 @@ func makeDestination(canary *flaggerv1.Canary, host string, weight int) istiov1a
if canary.Spec.Service.PortDiscovery &&
(len(canary.Spec.Service.Gateways) > 0 &&
canary.Spec.Service.Gateways[0] != "mesh" || canary.Spec.Service.Delegation) {
dest = istiov1alpha3.HTTPRouteDestination{
Destination: istiov1alpha3.Destination{
dest = istiov1beta1.HTTPRouteDestination{
Destination: istiov1beta1.Destination{
Host: host,
Port: &istiov1alpha3.PortSelector{
Port: &istiov1beta1.PortSelector{
Number: uint32(canary.Spec.Service.Port),
},
},

View File

@@ -31,7 +31,7 @@ import (
"github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
istiov1alpha1 "github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
)
func TestUnmarshalVirtualService(t *testing.T) {
@@ -69,7 +69,7 @@ func TestUnmarshalVirtualService(t *testing.T) {
}
`
var vs istiov1alpha3.VirtualService
var vs istiov1beta1.VirtualService
err := json.Unmarshal([]byte(body), &vs)
require.NoError(t, err)
}
@@ -87,13 +87,13 @@ func TestIstioRouter_Sync(t *testing.T) {
require.NoError(t, err)
// test insert
_, err = mocks.meshClient.NetworkingV1alpha3().DestinationRules("default").Get(context.TODO(), "podinfo-canary", metav1.GetOptions{})
_, err = mocks.meshClient.NetworkingV1beta1().DestinationRules("default").Get(context.TODO(), "podinfo-canary", metav1.GetOptions{})
require.NoError(t, err)
_, err = mocks.meshClient.NetworkingV1alpha3().DestinationRules("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
_, err = mocks.meshClient.NetworkingV1beta1().DestinationRules("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
require.Len(t, vs.Spec.Http, 1)
require.Len(t, vs.Spec.Http[0].Route, 2)
@@ -114,7 +114,7 @@ func TestIstioRouter_Sync(t *testing.T) {
require.NoError(t, err)
// verify
vs, err = mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err = mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Hosts, 2)
@@ -125,7 +125,7 @@ func TestIstioRouter_Sync(t *testing.T) {
vsClone.Spec.Gateways = gateways
totalGateways := len(mocks.canary.Spec.Service.Gateways)
vsGateways, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Update(context.TODO(), vsClone, metav1.UpdateOptions{})
vsGateways, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Update(context.TODO(), vsClone, metav1.UpdateOptions{})
require.NoError(t, err)
totalGateways++
@@ -137,7 +137,7 @@ func TestIstioRouter_Sync(t *testing.T) {
require.NoError(t, err)
// verify
vs, err = mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err = mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Gateways, totalGateways)
}
@@ -162,11 +162,11 @@ func TestIstioRouter_SetRoutes(t *testing.T) {
err := router.SetRoutes(mocks.canary, p, c, false)
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
var pRoute, cRoute istiov1alpha3.HTTPRouteDestination
var mirror *istiov1alpha3.Destination
var pRoute, cRoute istiov1beta1.HTTPRouteDestination
var mirror *istiov1beta1.Destination
for _, http := range vs.Spec.Http {
for _, route := range http.Route {
if route.Destination.Host == pHost {
@@ -195,7 +195,7 @@ func TestIstioRouter_SetRoutes(t *testing.T) {
}
err := router.SetRoutes(canary, 0, 10, false)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Http, 2)
@@ -240,7 +240,7 @@ func TestIstioRouter_SetRoutes(t *testing.T) {
err = router.Reconcile(canary)
require.NoError(t, err)
reconciledVS, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
reconciledVS, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
// routes should not be changed.
@@ -253,7 +253,7 @@ func TestIstioRouter_SetRoutes(t *testing.T) {
err = router.SetRoutes(canary, 50, 50, false)
require.NoError(t, err)
vs, err = mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err = mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Http, 2)
@@ -296,7 +296,7 @@ func TestIstioRouter_SetRoutes(t *testing.T) {
err = router.SetRoutes(canary, 100, 0, false)
require.NoError(t, err)
vs, err = mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err = mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Http, 2)
@@ -352,12 +352,12 @@ func TestIstioRouter_SetRoutes(t *testing.T) {
err := router.SetRoutes(mocks.canary, p, c, true)
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
var pRoute, cRoute istiov1alpha3.HTTPRouteDestination
var mirror *istiov1alpha3.Destination
var mirrorWeight *istiov1alpha3.Percent
var pRoute, cRoute istiov1beta1.HTTPRouteDestination
var mirror *istiov1beta1.Destination
var mirrorWeight *istiov1beta1.Percent
for _, http := range vs.Spec.Http {
for _, route := range http.Route {
if route.Destination.Host == pHost {
@@ -419,20 +419,20 @@ func TestIstioRouter_GetRoutes(t *testing.T) {
assert.False(t, m)
// Adjust vs to activate mirroring.
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
cHost := fmt.Sprintf("%s-canary", mocks.canary.Spec.TargetRef.Name)
for i, http := range vs.Spec.Http {
for _, route := range http.Route {
if route.Destination.Host == cHost {
vs.Spec.Http[i].Mirror = &istiov1alpha3.Destination{
vs.Spec.Http[i].Mirror = &istiov1beta1.Destination{
Host: cHost,
}
}
}
}
_, err = mocks.meshClient.NetworkingV1alpha3().VirtualServices(mocks.canary.Namespace).Update(context.TODO(), vs, metav1.UpdateOptions{})
_, err = mocks.meshClient.NetworkingV1beta1().VirtualServices(mocks.canary.Namespace).Update(context.TODO(), vs, metav1.UpdateOptions{})
require.NoError(t, err)
p, c, m, err = router.GetRoutes(mocks.canary)
@@ -454,7 +454,7 @@ func TestIstioRouter_HTTPRequestHeaders(t *testing.T) {
err := router.Reconcile(mocks.canary)
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
require.Len(t, vs.Spec.Http, 1)
assert.Equal(t, "15000", vs.Spec.Http[0].Headers.Request.Add["x-envoy-upstream-rq-timeout-ms"])
@@ -474,7 +474,7 @@ func TestIstioRouter_CORS(t *testing.T) {
err := router.Reconcile(mocks.canary)
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
require.NoError(t, err)
require.Len(t, vs.Spec.Http, 1)
@@ -495,7 +495,7 @@ func TestIstioRouter_ABTest(t *testing.T) {
require.NoError(t, err)
// test insert
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Http, 2)
@@ -506,14 +506,14 @@ func TestIstioRouter_ABTest(t *testing.T) {
err = router.SetRoutes(mocks.abtest, p, c, m)
require.NoError(t, err)
vs, err = mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
vs, err = mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
require.NoError(t, err)
pHost := fmt.Sprintf("%s-primary", mocks.abtest.Spec.TargetRef.Name)
cHost := fmt.Sprintf("%s-canary", mocks.abtest.Spec.TargetRef.Name)
pRoute := istiov1alpha3.HTTPRouteDestination{}
cRoute := istiov1alpha3.HTTPRouteDestination{}
var mirror *istiov1alpha3.Destination
pRoute := istiov1beta1.HTTPRouteDestination{}
cRoute := istiov1beta1.HTTPRouteDestination{}
var mirror *istiov1beta1.Destination
for _, http := range vs.Spec.Http {
for _, route := range http.Route {
@@ -544,7 +544,7 @@ func TestIstioRouter_GatewayPort(t *testing.T) {
err := router.Reconcile(mocks.canary)
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
port := vs.Spec.Http[0].Route[0].Destination.Port.Number
@@ -568,7 +568,7 @@ func TestIstioRouter_Delegate(t *testing.T) {
err := router.Reconcile(mocks.canary)
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
assert.Equal(t, 0, len(vs.Spec.Hosts))
@@ -610,8 +610,8 @@ func TestIstioRouter_Finalize(t *testing.T) {
kubeClient: mocks.kubeClient,
}
flaggerSpec := &istiov1alpha3.VirtualServiceSpec{
Http: []istiov1alpha3.HTTPRoute{
flaggerSpec := &istiov1beta1.VirtualServiceSpec{
Http: []istiov1beta1.HTTPRoute{
{
Match: mocks.canary.Spec.Service.Match,
Rewrite: mocks.canary.Spec.Service.GetIstioRewrite(),
@@ -622,15 +622,15 @@ func TestIstioRouter_Finalize(t *testing.T) {
},
}
kubectlSpec := &istiov1alpha3.VirtualServiceSpec{
kubectlSpec := &istiov1beta1.VirtualServiceSpec{
Hosts: []string{"podinfo"},
Gateways: []string{"istio-system/ingressgateway"},
Http: []istiov1alpha3.HTTPRoute{
Http: []istiov1beta1.HTTPRoute{
{
Match: nil,
Route: []istiov1alpha3.HTTPRouteDestination{
Route: []istiov1beta1.HTTPRouteDestination{
{
Destination: istiov1alpha3.Destination{Host: "podinfo"},
Destination: istiov1beta1.Destination{Host: "podinfo"},
},
},
},
@@ -639,7 +639,7 @@ func TestIstioRouter_Finalize(t *testing.T) {
tables := []struct {
router *IstioRouter
spec *istiov1alpha3.VirtualServiceSpec
spec *istiov1beta1.VirtualServiceSpec
shouldError bool
createVS bool
canary *v1beta1.Canary
@@ -659,7 +659,7 @@ func TestIstioRouter_Finalize(t *testing.T) {
for _, table := range tables {
var err error
if table.createVS {
vs, err := router.istioClient.NetworkingV1alpha3().VirtualServices(table.canary.Namespace).Get(context.TODO(), table.canary.Name, metav1.GetOptions{})
vs, err := router.istioClient.NetworkingV1beta1().VirtualServices(table.canary.Namespace).Get(context.TODO(), table.canary.Name, metav1.GetOptions{})
require.NoError(t, err)
if vs.Annotations == nil {
@@ -672,9 +672,9 @@ func TestIstioRouter_Finalize(t *testing.T) {
require.NoError(t, err)
vs.Annotations[configAnnotation] = string(b)
case "kubectl":
vs.Annotations[kubectlAnnotation] = `{"apiVersion": "networking.istio.io/v1alpha3","kind": "VirtualService","metadata": {"annotations": {},"name": "podinfo","namespace": "test"}, "spec": {"gateways": ["istio-system/ingressgateway"],"hosts": ["podinfo"],"http": [{"route": [{"destination": {"host": "podinfo"}}]}]}}`
vs.Annotations[kubectlAnnotation] = `{"apiVersion": "networking.istio.io/v1beta1","kind": "VirtualService","metadata": {"annotations": {},"name": "podinfo","namespace": "test"}, "spec": {"gateways": ["istio-system/ingressgateway"],"hosts": ["podinfo"],"http": [{"route": [{"destination": {"host": "podinfo"}}]}]}}`
}
_, err = router.istioClient.NetworkingV1alpha3().VirtualServices(table.canary.Namespace).Update(context.TODO(), vs, metav1.UpdateOptions{})
_, err = router.istioClient.NetworkingV1beta1().VirtualServices(table.canary.Namespace).Update(context.TODO(), vs, metav1.UpdateOptions{})
require.NoError(t, err)
}
@@ -691,7 +691,7 @@ func TestIstioRouter_Finalize(t *testing.T) {
}
if table.spec != nil {
vs, err := router.istioClient.NetworkingV1alpha3().VirtualServices(table.canary.Namespace).Get(context.TODO(), table.canary.Name, metav1.GetOptions{})
vs, err := router.istioClient.NetworkingV1beta1().VirtualServices(table.canary.Namespace).Get(context.TODO(), table.canary.Name, metav1.GetOptions{})
require.NoError(t, err)
require.Equal(t, *table.spec, vs.Spec)
}
@@ -712,7 +712,7 @@ func TestIstioRouter_Match(t *testing.T) {
require.NoError(t, err)
// test insert
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Http, 2)
assert.Len(t, vs.Spec.Http[0].Match, 1) // check for abtest-canary
@@ -720,7 +720,7 @@ func TestIstioRouter_Match(t *testing.T) {
assert.Len(t, vs.Spec.Http[1].Match, 0) // check for abtest-primary
// Test Case that is service.match exists and multiple analysis.match
mocks.abtest.Spec.Service.Match = []istiov1alpha3.HTTPMatchRequest{
mocks.abtest.Spec.Service.Match = []istiov1beta1.HTTPMatchRequest{
{
Name: "podinfo",
Uri: &istiov1alpha1.StringMatch{
@@ -732,7 +732,7 @@ func TestIstioRouter_Match(t *testing.T) {
IgnoreUriCase: true,
},
}
mocks.abtest.Spec.Analysis.Match = []istiov1alpha3.HTTPMatchRequest{
mocks.abtest.Spec.Analysis.Match = []istiov1beta1.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"x-user-type": {
@@ -756,7 +756,7 @@ func TestIstioRouter_Match(t *testing.T) {
err = router.Reconcile(mocks.abtest)
require.NoError(t, err)
vs, err = mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
vs, err = mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "abtest", metav1.GetOptions{})
require.NoError(t, err)
assert.Len(t, vs.Spec.Http, 2)
assert.Len(t, vs.Spec.Http[0].Match, 2) // check for abtest-canary
@@ -787,7 +787,7 @@ func newTestCanaryTCP() *flaggerv1.Canary {
Port: 9898,
PortDiscovery: true,
AppProtocol: "TCP",
Match: []istiov1alpha3.HTTPMatchRequest{
Match: []istiov1beta1.HTTPMatchRequest{
{
Port: 9898,
},
@@ -838,10 +838,10 @@ func TestIstioRouter_SetRoutesTCP(t *testing.T) {
err := router.SetRoutes(mocks.canary, p, c, false)
require.NoError(t, err)
vs, err := mocks.meshClient.NetworkingV1alpha3().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
vs, err := mocks.meshClient.NetworkingV1beta1().VirtualServices("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
require.NoError(t, err)
var pRoute, cRoute istiov1alpha3.HTTPRouteDestination
var pRoute, cRoute istiov1beta1.HTTPRouteDestination
for _, tcp := range vs.Spec.Tcp {
for _, route := range tcp.Route {
if route.Destination.Host == pHost {

View File

@@ -31,7 +31,7 @@ import (
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
gatewayapiv1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1"
istiov1alpha1 "github.com/fluxcd/flagger/pkg/apis/istio/common/v1alpha1"
istiov1alpha3 "github.com/fluxcd/flagger/pkg/apis/istio/v1alpha3"
istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1"
clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
fakeFlagger "github.com/fluxcd/flagger/pkg/client/clientset/versioned/fake"
"github.com/fluxcd/flagger/pkg/logger"
@@ -143,24 +143,24 @@ func newTestCanary() *flaggerv1.Canary {
Port: 9898,
PortDiscovery: true,
AppProtocol: "http",
Headers: &istiov1alpha3.Headers{
Request: &istiov1alpha3.HeaderOperations{
Headers: &istiov1beta1.Headers{
Request: &istiov1beta1.HeaderOperations{
Add: map[string]string{
"x-envoy-upstream-rq-timeout-ms": "15000",
},
Remove: []string{"test"},
},
Response: &istiov1alpha3.HeaderOperations{
Response: &istiov1beta1.HeaderOperations{
Remove: []string{"token"},
},
},
CorsPolicy: &istiov1alpha3.CorsPolicy{
CorsPolicy: &istiov1beta1.CorsPolicy{
AllowMethods: []string{
"GET",
"POST",
},
},
Match: []istiov1alpha3.HTTPMatchRequest{
Match: []istiov1beta1.HTTPMatchRequest{
{
Name: "podinfo",
Uri: &istiov1alpha1.StringMatch{
@@ -172,7 +172,7 @@ func newTestCanary() *flaggerv1.Canary {
IgnoreUriCase: true,
},
},
Retries: &istiov1alpha3.HTTPRetry{
Retries: &istiov1beta1.HTTPRetry{
Attempts: 10,
PerTryTimeout: "30s",
RetryOn: "connect-failure,gateway-error",
@@ -225,7 +225,7 @@ func newTestCanaryAppMesh() *flaggerv1.Canary {
Hosts: []string{"*"},
Backends: []string{"backend.default"},
Timeout: "30s",
Retries: &istiov1alpha3.HTTPRetry{
Retries: &istiov1beta1.HTTPRetry{
Attempts: 5,
PerTryTimeout: "gateway-error",
RetryOn: "5s",
@@ -322,7 +322,7 @@ func newTestABTest() *flaggerv1.Canary {
}, Analysis: &flaggerv1.CanaryAnalysis{
Threshold: 10,
Iterations: 2,
Match: []istiov1alpha3.HTTPMatchRequest{
Match: []istiov1beta1.HTTPMatchRequest{
{
Headers: map[string]istiov1alpha1.StringMatch{
"x-user-type": {

View File

@@ -16,5 +16,5 @@ limitations under the License.
package version
var VERSION = "1.36.1"
var VERSION = "1.38.0"
var REVISION = "unknown"

View File

@@ -117,6 +117,28 @@ done
echo '✔ Canary initialization test passed'
echo '>>> Waiting for primary spec to be updated'
# Update gloo upstream on slow start config which will trigger update on flagger upstreams
kubectl -n gloo-system patch upstream config-upstream --type json --patch='[ { "op": "replace", "path": "/spec/loadBalancerConfig/roundRobin/slowStartConfig/minWeightPercent", "value": 20 } ]'
retries=50
count=0
ok=false
until ${ok}; do
kubectl -n test get upstream/test-podinfo-canaryupstream-80 -ojson | jq '.spec.loadBalancerConfig.roundRobin.slowStartConfig.minWeightPercent' | grep '20' && ok=true || ok=false
sleep 5
count=$(($count + 1))
if [[ ${count} -eq ${retries} ]]; then
kubectl -n gloo-system logs deployment/flagger
echo "No more retries left"
exit 1
fi
done
echo '✔ Canary reconcilation test passed'
echo '>>> Triggering canary deployment'
kubectl -n test set image deployment/podinfo podinfod=ghcr.io/stefanprodan/podinfo:6.0.1

Some files were not shown because too many files have changed in this diff Show More