diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0727db81e..b626c09d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
# Table of Contents
+- [v1.41.1](#v1411)
+- [v1.41.0](#v1410)
- [v1.40.3](#v1403)
- [v1.40.2](#v1402)
- [v1.40.1](#v1401)
@@ -96,6 +98,25 @@
- [v0.2.0](#v020)
- [v0.1.0](#v010)
+## [v1.41.1]
+> Release date: 2024/10/22
+
+### Fixes
+- `deck gateway validate` for Konnect supports Konnect configs passed by CLI flags now.
+Earlier, the validation was failing if control plane information was passed via CLI flags.
+
+## [v1.41.0]
+> Release date: 2024/10/21
+
+### Added
+- `deck gateway validate` command now supports Konnect. Konnect entities can be validated online with this change.
+[#1335](https://github.com/Kong/deck/pull/1335)
+
+### Fixes
+- Quoted type constraints are removed for Terraform. Type constraints in quotes were required in Terraform <= 0.11,
+It is now deprecated and will be removed in a future Terraform versions. Thus, removed them from kong2tf generation, so as
+to avoid potential errors in `terraform apply`. [#1412](https://github.com/Kong/deck/pull/1412)
+
## [v1.40.3]
> Release date: 2024/09/26
@@ -1822,6 +1843,8 @@ No breaking changes have been introduced in this release.
Debut release of decK
+[v1.41.1]: https://github.com/Kong/deck/compare/v1.40.0...v1.41.1
+[v1.41.0]: https://github.com/Kong/deck/compare/v1.40.3...v1.41.0
[v1.40.3]: https://github.com/Kong/deck/compare/v1.40.2...v1.40.3
[v1.40.2]: https://github.com/Kong/deck/compare/v1.40.1...v1.40.2
[v1.40.1]: https://github.com/Kong/deck/compare/v1.40.0...v1.40.1
diff --git a/README.md b/README.md
index d3ea79ec0..cd9bcc971 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ the GitHub [release page](https://github.com/kong/deck/releases)
or install by downloading the binary:
```shell
-$ curl -sL https://github.com/kong/deck/releases/download/v1.40.3/deck_1.40.3_linux_amd64.tar.gz -o deck.tar.gz
+$ curl -sL https://github.com/kong/deck/releases/download/v1.41.1/deck_1.41.1_linux_amd64.tar.gz -o deck.tar.gz
$ tar -xf deck.tar.gz -C /tmp
$ sudo cp /tmp/deck /usr/local/bin/
```
@@ -84,7 +84,7 @@ If you are on Windows, you can download the binary from the GitHub
[release page](https://github.com/kong/deck/releases) or via PowerShell:
```shell
-$ curl -sL https://github.com/kong/deck/releases/download/v1.40.3/deck_1.40.3_windows_amd64.tar.gz -o deck.tar.gz
+$ curl -sL https://github.com/kong/deck/releases/download/v1.41.1/deck_1.41.1_windows_amd64.tar.gz -o deck.tar.gz
$ tar -xzvf deck.tar.gz
```
diff --git a/cmd/gateway_validate.go b/cmd/gateway_validate.go
index 271f2463d..0d2ee3690 100644
--- a/cmd/gateway_validate.go
+++ b/cmd/gateway_validate.go
@@ -27,9 +27,6 @@ var (
func executeValidate(cmd *cobra.Command, _ []string) error {
mode := getMode(nil)
- if validateOnline && mode == modeKonnect {
- return fmt.Errorf("online validation not yet supported in konnect mode")
- }
_ = sendAnalytics("validate", "", mode)
// read target file
// this does json schema validation as well
@@ -45,7 +42,7 @@ func executeValidate(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
var kongClient *kong.Client
if validateOnline {
- kongClient, err = getKongClient(ctx, targetContent)
+ kongClient, err = getKongClient(ctx, targetContent, mode)
if err != nil {
return err
}
@@ -143,10 +140,14 @@ func executeValidate(cmd *cobra.Command, _ []string) error {
return err
}
- if validateKonnectCompatibility {
- if errs := validate.KonnectCompatibility(targetContent); len(errs) != 0 {
+ if validateKonnectCompatibility || (mode == modeKonnect && validateOnline) {
+ if errs := validate.KonnectCompatibility(targetContent, dumpConfig); len(errs) != 0 {
return validate.ErrorsWrapper{Errors: errs}
}
+
+ if validateCmdRBACResourcesOnly {
+ return fmt.Errorf("[rbac] not yet supported by konnect")
+ }
}
if validateOnline {
@@ -212,7 +213,7 @@ this command unless --online flag is used.
return preRunSilenceEventsFlag()
}
- if validateOnline {
+ if online {
short = short + " (online)"
long = long + "Validates against the Kong API, via communication with Kong. This increases the\n" +
"time for validation but catches significant errors. No resource is created in Kong.\n" +
@@ -255,6 +256,9 @@ this command unless --online flag is used.
validateCmd.Flags().BoolVar(&validateKonnectCompatibility, "konnect-compatibility",
false, "validate that the state file(s) are ready to be deployed to Konnect")
+ validateCmd.MarkFlagsMutuallyExclusive("konnect-compatibility", "workspace")
+ validateCmd.MarkFlagsMutuallyExclusive("konnect-compatibility", "rbac-resources-only")
+
if err := ensureGetAllMethods(); err != nil {
panic(err.Error())
}
@@ -285,9 +289,14 @@ func validateWithKong(
return validator.Validate(parsedFormatVersion)
}
-func getKongClient(ctx context.Context, targetContent *file.Content) (*kong.Client, error) {
+func getKongClient(
+ ctx context.Context, targetContent *file.Content, mode mode,
+) (*kong.Client, error) {
workspaceName := validateWorkspace
if validateWorkspace != "" {
+ if mode == modeKonnect {
+ return nil, fmt.Errorf("[workspaces] not supported by Konnect - use control planes instead")
+ }
// check if workspace exists
workspaceName := getWorkspaceName(validateWorkspace, targetContent, false)
workspaceExists, err := workspaceExists(ctx, rootConfig, workspaceName)
@@ -299,10 +308,22 @@ func getKongClient(ctx context.Context, targetContent *file.Content) (*kong.Clie
}
}
- wsConfig := rootConfig.ForWorkspace(workspaceName)
- kongClient, err := reconcilerUtils.GetKongClient(wsConfig)
- if err != nil {
- return nil, err
+ var (
+ kongClient *kong.Client
+ err error
+ )
+ if mode == modeKonnect {
+ kongClient, err = GetKongClientForKonnectMode(ctx, &konnectConfig)
+ if err != nil {
+ return nil, err
+ }
+ dumpConfig.KonnectControlPlane = konnectControlPlane
+ } else {
+ wsConfig := rootConfig.ForWorkspace(workspaceName)
+ kongClient, err = reconcilerUtils.GetKongClient(wsConfig)
+ if err != nil {
+ return nil, err
+ }
}
return kongClient, nil
}
diff --git a/go.mod b/go.mod
index 05c05f8c1..99c50d77f 100644
--- a/go.mod
+++ b/go.mod
@@ -18,42 +18,94 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
- github.com/spf13/viper v1.18.2
+ github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
golang.org/x/sync v0.8.0
k8s.io/api v0.31.0
k8s.io/apiextensions-apiserver v0.31.0
k8s.io/apimachinery v0.31.0
+ k8s.io/client-go v0.31.0
k8s.io/code-generator v0.31.0
sigs.k8s.io/gateway-api v1.1.0
sigs.k8s.io/yaml v1.4.0
)
require (
+ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
+ github.com/MakeNowJust/heredoc v1.0.0 // indirect
+ github.com/Microsoft/go-winio v0.6.1 // indirect
+ github.com/avast/retry-go/v4 v4.6.0 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+ github.com/chai2010/gettext-go v1.0.2 // indirect
+ github.com/distribution/reference v0.5.0 // indirect
+ github.com/docker/docker v26.1.4+incompatible // indirect
+ github.com/docker/go-connections v0.5.0 // indirect
+ github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
+ github.com/evanphx/json-patch v5.9.0+incompatible // indirect
+ github.com/evanphx/json-patch/v5 v5.9.0 // indirect
+ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
+ github.com/fatih/camelcase v1.0.0 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
+ github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
+ github.com/go-errors/errors v1.4.2 // indirect
+ github.com/google/btree v1.1.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
+ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
+ github.com/gorilla/websocket v1.5.1 // indirect
+ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/hashicorp/go-memdb v1.3.4 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
+ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
+ github.com/mitchellh/go-wordwrap v1.0.1 // indirect
+ github.com/moby/docker-image-spec v1.3.1 // indirect
+ github.com/moby/spdystream v0.4.0 // indirect
+ github.com/moby/term v0.5.0 // indirect
+ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
+ github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/pb33f/doctor v0.0.6 // indirect
github.com/pb33f/libopenapi v0.16.13 // indirect
github.com/pb33f/libopenapi-validator v0.0.49 // indirect
+ github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
+ github.com/sethvargo/go-password v0.3.0 // indirect
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
+ github.com/sirupsen/logrus v1.9.3 // indirect
github.com/ssgelm/cookiejarparser v1.0.1 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
+ github.com/xlab/treeprint v1.2.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
+ go.opentelemetry.io/otel v1.28.0 // indirect
+ go.opentelemetry.io/otel/metric v1.28.0 // indirect
+ go.opentelemetry.io/otel/trace v1.28.0 // indirect
+ go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
+ go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28 // indirect
+ golang.org/x/oauth2 v0.21.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
+ gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
+ k8s.io/cli-runtime v0.30.1 // indirect
+ k8s.io/component-base v0.31.0 // indirect
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
+ k8s.io/kubectl v0.30.1 // indirect
+ sigs.k8s.io/kind v0.23.0 // indirect
+ sigs.k8s.io/kustomize/api v0.17.2 // indirect
+ sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect
)
require (
@@ -96,6 +148,7 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/kong/go-slugify v1.0.0 // indirect
github.com/kong/kubernetes-ingress-controller/v3 v3.2.4
+ github.com/kong/kubernetes-testing-framework v0.47.1
github.com/kong/semver/v4 v4.0.1 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
@@ -108,7 +161,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-unidecode v0.2.0 // indirect
- github.com/pelletier/go-toml/v2 v2.1.0 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/pterm/pterm v0.12.79 // indirect
diff --git a/go.sum b/go.sum
index 53dee8c78..4cd80a5b7 100644
--- a/go.sum
+++ b/go.sum
@@ -6,14 +6,20 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Kong/go-diff v1.2.2 h1:KKKaqHc8IxuguFVIZMNt3bi6YuC/t9r7BGD8bOOpSgM=
github.com/Kong/go-diff v1.2.2/go.mod h1:nlvdwVZQk3Rm+tbI0cDmKFrOjghtcZTrZBp+UruvvA8=
github.com/Kong/gojsondiff v1.3.2 h1:qIOVq2mUXt+NXy8Be5gRUee9TP3Ve0MbQSafg9bXKZE=
github.com/Kong/gojsondiff v1.3.2/go.mod h1:DiIxtU59q4alK7ecP+7k56C5UjgOviJ5gQVR2esEhYw=
github.com/Kong/yaml v1.0.0 h1:OWOxtLEamLYKZzcrfoH76imAwSi9FgSZapxg1Kh6IBA=
github.com/Kong/yaml v1.0.0/go.mod h1:gVzJ3lyC0UdO7kZxmCpwn0Vj20y/02cFnDpHBirGrSQ=
+github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
+github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
@@ -23,11 +29,17 @@ github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4=
github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/adrg/strutil v0.3.0 h1:bi/HB2zQbDihC8lxvATDTDzkT4bG7PATtVnDYp5rvq4=
github.com/adrg/strutil v0.3.0/go.mod h1:Jz0wzBVE6Uiy9wxo62YEqEY1Nwto3QlLl1Il5gkLKWU=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
+github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA=
+github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
@@ -36,26 +48,42 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
+github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
+github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daveshanley/vacuum v0.9.15 h1:QeSHYhbcB7x4chhOTsdxlZNBdipbFthusQkzeISplT0=
github.com/daveshanley/vacuum v0.9.15/go.mod h1:xTTqOXVYJcEtvRe9YD07rhb0eK4zG6MRRjrmMadP5Kg=
+github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
+github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU=
+github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
+github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 h1:O7I1iuzEA7SG+dK8ocOBSlYAA9jBUmCYl/Qa7ey7JAM=
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
@@ -68,23 +96,41 @@ github.com/dprotaso/go-yit v0.0.0-20240618133044-5a0af90af097 h1:f5nA5Ys8RXqFXtK
github.com/dprotaso/go-yit v0.0.0-20240618133044-5a0af90af097/go.mod h1:FTAVyH6t+SlS97rv6EXRVuBDLkQqcIe/xQw9f4IFUI4=
github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=
github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
+github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
+github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
+github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
+github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
+github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
+github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
+github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
+github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
+github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
@@ -101,22 +147,31 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
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=
+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.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.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.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
+github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-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.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -131,16 +186,25 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
+github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gosimple/slug v1.14.0 h1:RtTL/71mJNDfpUbCOmnf/XFkzKRtD6wL6Uy+3akm4Es=
github.com/gosimple/slug v1.14.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ=
github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o=
github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
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 v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
@@ -191,6 +255,8 @@ github.com/kong/go-slugify v1.0.0 h1:vCFAyf2sdoSlBtLcrmDWUFn0ohlpKiKvQfXZkO5vSKY
github.com/kong/go-slugify v1.0.0/go.mod h1:dbR2h3J2QKXQ1k0aww6cN7o4cIcwlWflr6RKRdcoaiw=
github.com/kong/kubernetes-ingress-controller/v3 v3.2.4 h1:5QKzRMHWAePwa9HGj3xtvgridzeG72xd3BftDP+PcjU=
github.com/kong/kubernetes-ingress-controller/v3 v3.2.4/go.mod h1:kbbsyyNw/2HdURecav7iFcjAOtNXoUP5CfYFYJgiJq4=
+github.com/kong/kubernetes-testing-framework v0.47.1 h1:BE2mQLC0Zj/NC5Y8B1Nm5VZymmrdVfu7cfwVKSobWtg=
+github.com/kong/kubernetes-testing-framework v0.47.1/go.mod h1:9E53E99mlIGLgBU7R529X7IAUnVY8H1IqZecvGLZeco=
github.com/kong/semver/v4 v4.0.1 h1:DIcNR8W3gfx0KabFBADPalxxsp+q/5COwIFkkhrFQ2Y=
github.com/kong/semver/v4 v4.0.1/go.mod h1:LImQ0oT15pJvSns/hs2laLca2zcYoHu5EsSNY0J6/QA=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -202,6 +268,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
+github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik=
@@ -220,15 +288,31 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
+github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
+github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
+github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mozillazg/go-unidecode v0.2.0 h1:vFGEzAH9KSwyWmXCOblazEWDh7fOkpmy/Z4ArmamSUc=
github.com/mozillazg/go-unidecode v0.2.0/go.mod h1:zB48+/Z5toiRolOZy9ksLryJ976VIwmDmpQ2quyt1aA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -248,19 +332,28 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
+github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/pb33f/doctor v0.0.6 h1:su/mIujJy0rB8KsdpTl7cC4RAHZdTyB7V5SjXu+xVWE=
github.com/pb33f/doctor v0.0.6/go.mod h1:yBs5hFHAoo/eeFvKN9sWwmHmgEPJ2SaotYOJc05GdMU=
github.com/pb33f/libopenapi v0.16.13 h1:uR/W3Rit/yxRWG5DWal26PdEnEq4mu/3cYjbkK6LHm0=
github.com/pb33f/libopenapi v0.16.13/go.mod h1:8/lZGTZmxybpTPOggS6LefdrYvsQ5kbirD364TceyQo=
github.com/pb33f/libopenapi-validator v0.0.49 h1:oJ4Jukib2pCvW0ccdVVyIyK/s5LCNvAuNt1U+PnGgEs=
github.com/pb33f/libopenapi-validator v0.0.49/go.mod h1:kU1JYyXIRlpmsWx3NkL+drNNttLADMgdaNzJgXDhec0=
-github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
-github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
+github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
+github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
+github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI=
github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg=
github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE=
@@ -276,6 +369,7 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
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/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
@@ -286,12 +380,16 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPO
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sethvargo/go-password v0.3.0 h1:OLFHZ91Z7NiNP3dnaPxLxCDXlb6TBuxFzMvv6bu+Ptw=
+github.com/sethvargo/go-password v0.3.0/go.mod h1:p6we8DZ0eyYXof9pon7Cqrw98N4KTaYiadDml1dUEEw=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
@@ -302,13 +400,15 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
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/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
-github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
+github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
+github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/ssgelm/cookiejarparser v1.0.1 h1:cRdXauUbOTFzTPJFaeiWbHnQ+tRGlpKKzvIK9PUekE4=
github.com/ssgelm/cookiejarparser v1.0.1/go.mod h1:DUfC0mpjIzlDN7DzKjXpHj0qMI5m9VrZuz3wSlI+OEI=
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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@@ -345,6 +445,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
+github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
+github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
@@ -359,21 +461,53 @@ github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
+go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
+go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY=
+go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
+go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
+go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
+go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
+go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
+go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
+go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
+go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
+go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
+go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
+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=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28 h1:zLxFnORHDFTSkJPawMU7LzsuGQJ4MUFS653jJHpORow=
+go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y=
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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
+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.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.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-20180906233101-161cd47e91fd/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-20191027093000-83d349e8ac1a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -387,7 +521,11 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
+golang.org/x/oauth2 v0.21.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-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=
@@ -395,6 +533,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.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-20180909124046-d0be0721c37e/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=
@@ -412,11 +551,13 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -429,6 +570,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
@@ -441,7 +583,13 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -454,12 +602,30 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
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/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/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-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
+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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
+google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
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=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
@@ -470,6 +636,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
+gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
@@ -488,20 +656,32 @@ gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
+gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
+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.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo=
k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE=
k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk=
k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk=
k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc=
k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
+k8s.io/cli-runtime v0.30.1 h1:kSBBpfrJGS6lllc24KeniI9JN7ckOOJKnmFYH1RpTOw=
+k8s.io/cli-runtime v0.30.1/go.mod h1:zhHgbqI4J00pxb6gM3gJPVf2ysDjhQmQtnTxnMScab8=
+k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8=
+k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU=
k8s.io/code-generator v0.31.0 h1:w607nrMi1KeDKB3/F/J4lIoOgAwc+gV9ZKew4XRfMp8=
k8s.io/code-generator v0.31.0/go.mod h1:84y4w3es8rOJOUUP1rLsIiGlO1JuEaPFXQPA9e/K6U0=
+k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs=
+k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo=
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.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f h1:0LQagt0gDpKqvIkAMPaRGcXawNMouPECM1+F9BVxEaM=
k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f/go.mod h1:S9tOR0FxgyusSNR+MboCuiDpVWkAifZvaYI1Q2ubgro=
+k8s.io/kubectl v0.30.1 h1:sHFIRI3oP0FFZmBAVEE8ErjnTyXDPkBcvO88mH9RjuY=
+k8s.io/kubectl v0.30.1/go.mod h1:7j+L0Cc38RYEcx+WH3y44jRBe1Q1jxdGPKkX0h4iDq0=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw=
@@ -510,6 +690,12 @@ sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM=
sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs=
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/kind v0.23.0 h1:8fyDGWbWTeCcCTwA04v4Nfr45KKxbSPH1WO9K+jVrBg=
+sigs.k8s.io/kind v0.23.0/go.mod h1:ZQ1iZuJLh3T+O8fzhdi3VWcFTzsdXtNv2ppsHc8JQ7s=
+sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g=
+sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0=
+sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ=
+sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
diff --git a/kong2kic/builder_v2_gw_api.go b/kong2kic/builder_v2_gw_api.go
index 74b9a3db7..a30d4e21f 100644
--- a/kong2kic/builder_v2_gw_api.go
+++ b/kong2kic/builder_v2_gw_api.go
@@ -24,7 +24,7 @@ func (b *KICv2GatewayAPIBuilder) buildServices(content *file.Content) {
}
func (b *KICv2GatewayAPIBuilder) buildRoutes(content *file.Content) {
- err := populateKICIngressesWithGatewayAPI(content, b.kicContent)
+ err := populateKICIngressesWithAnnotations(content, b.kicContent)
if err != nil {
log.Fatal(err)
}
diff --git a/kong2kic/builder_v3_gw_api.go b/kong2kic/builder_v3_gw_api.go
index 4f1b6820c..81f62b8d7 100644
--- a/kong2kic/builder_v3_gw_api.go
+++ b/kong2kic/builder_v3_gw_api.go
@@ -24,7 +24,7 @@ func (b *KICv3GatewayAPIBuider) buildServices(content *file.Content) {
}
func (b *KICv3GatewayAPIBuider) buildRoutes(content *file.Content) {
- err := populateKICIngressesWithGatewayAPI(content, b.kicContent)
+ err := populateKICIngressesWithAnnotations(content, b.kicContent)
if err != nil {
log.Fatal(err)
}
diff --git a/kong2kic/ca_certificate.go b/kong2kic/ca_certificate.go
index a9a65a075..7cd4e92a2 100644
--- a/kong2kic/ca_certificate.go
+++ b/kong2kic/ca_certificate.go
@@ -3,6 +3,8 @@ package kong2kic
import (
"crypto/sha256"
"fmt"
+ "log"
+ "strings"
"github.com/kong/go-database-reconciler/pkg/file"
k8scorev1 "k8s.io/api/core/v1"
@@ -22,11 +24,28 @@ func populateKICCACertificate(content *file.Content, file *KICContent) {
secret.ObjectMeta.Name = calculateSlug(secretName)
secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
secret.StringData = make(map[string]string)
- secret.StringData["ca.crt"] = *caCert.Cert
+ if caCert.Cert != nil {
+ secret.StringData["ca.crt"] = *caCert.Cert
+ } else {
+ log.Println("CA Certificate is empty. This is not recommended." +
+ "Please, provide a certificate for the CA before generating Kong Ingress Controller manifests.")
+ continue
+ }
if caCert.CertDigest != nil {
secret.StringData["ca.digest"] = *caCert.CertDigest
}
+ // add konghq.com/tags annotation if cacert.Tags is not nil
+ if caCert.Tags != nil {
+ var tags []string
+ for _, tag := range caCert.Tags {
+ if tag != nil {
+ tags = append(tags, *tag)
+ }
+ }
+ secret.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
+ }
+
file.Secrets = append(file.Secrets, secret)
}
}
diff --git a/kong2kic/certificate.go b/kong2kic/certificate.go
index 6d409b37d..48c4e9daf 100644
--- a/kong2kic/certificate.go
+++ b/kong2kic/certificate.go
@@ -3,6 +3,8 @@ package kong2kic
import (
"crypto/sha256"
"fmt"
+ "log"
+ "strings"
"github.com/kong/go-database-reconciler/pkg/file"
k8scorev1 "k8s.io/api/core/v1"
@@ -22,10 +24,27 @@ func populateKICCertificates(content *file.Content, file *KICContent) {
secret.ObjectMeta.Name = calculateSlug(secretName)
secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
secret.StringData = make(map[string]string)
- secret.StringData["tls.crt"] = *cert.Cert
- secret.StringData["tls.key"] = *cert.Key
+ if cert.Cert != nil && cert.Key != nil {
+ secret.StringData["tls.crt"] = *cert.Cert
+ secret.StringData["tls.key"] = *cert.Key
+ } else {
+ log.Println("Certificate or Key is empty. This is not recommended." +
+ "Please, provide a certificate and key before generating Kong Ingress Controller manifests.")
+ continue
+ }
// what to do with SNIs?
+ // add konghq.com/tags annotation if cert.Tags is not nil
+ if cert.Tags != nil {
+ var tags []string
+ for _, tag := range cert.Tags {
+ if tag != nil {
+ tags = append(tags, *tag)
+ }
+ }
+ secret.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
+ }
+
file.Secrets = append(file.Secrets, secret)
}
}
diff --git a/kong2kic/consumer.go b/kong2kic/consumer.go
index a23a4f7c1..d0b30e203 100644
--- a/kong2kic/consumer.go
+++ b/kong2kic/consumer.go
@@ -1,31 +1,40 @@
package kong2kic
import (
- "encoding/json"
"log"
- "strconv"
"github.com/kong/go-database-reconciler/pkg/file"
kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
- k8scorev1 "k8s.io/api/core/v1"
- apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
+// Function to populate KIC Consumers and their credentials
func populateKICConsumers(content *file.Content, file *KICContent) error {
- // Iterate Kong Consumers and copy them into KongConsumer
- for i := range content.Consumers {
- consumer := content.Consumers[i]
-
- var kongConsumer kicv1.KongConsumer
- kongConsumer.APIVersion = KICAPIVersion
- kongConsumer.Kind = "KongConsumer"
- kongConsumer.ObjectMeta.Name = calculateSlug(*consumer.Username)
- kongConsumer.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- kongConsumer.Username = *consumer.Username
+ for _, consumer := range content.Consumers {
+ if consumer.Username == nil {
+ log.Println("Consumer username is empty. Please provide a username for the consumer.")
+ continue
+ }
+ username := *consumer.Username
+ kongConsumer := kicv1.KongConsumer{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: KICAPIVersion,
+ Kind: "KongConsumer",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(username),
+ Annotations: map[string]string{IngressClass: ClassName},
+ },
+ Username: username,
+ }
if consumer.CustomID != nil {
kongConsumer.CustomID = *consumer.CustomID
}
+ // Add tags to annotations
+ addTagsToAnnotations(consumer.Tags, kongConsumer.ObjectMeta.Annotations)
+
+ // Populate credentials
populateKICKeyAuthSecrets(&consumer, &kongConsumer, file)
populateKICHMACSecrets(&consumer, &kongConsumer, file)
populateKICJWTAuthSecrets(&consumer, &kongConsumer, file)
@@ -34,38 +43,17 @@ func populateKICConsumers(content *file.Content, file *KICContent) error {
populateKICACLGroupSecrets(&consumer, &kongConsumer, file)
populateKICMTLSAuthSecrets(&consumer, &kongConsumer, file)
- // for each consumer.plugin, create a KongPlugin and a plugin annotation in the kongConsumer
- // to link the plugin
+ // Handle plugins associated with the consumer
for _, plugin := range consumer.Plugins {
- var kongPlugin kicv1.KongPlugin
- kongPlugin.APIVersion = KICAPIVersion
- kongPlugin.Kind = KongPluginKind
- kongPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- if plugin.Name != nil {
- kongPlugin.PluginName = *plugin.Name
- kongPlugin.ObjectMeta.Name = calculateSlug(*consumer.Username + "-" + *plugin.Name)
- } else {
- log.Println("Plugin name is empty. This is not recommended." +
- "Please, provide a name for the plugin before generating Kong Ingress Controller manifests.")
- continue
- }
-
- // transform the plugin config from map[string]interface{} to apiextensionsv1.JSON
- var configJSON apiextensionsv1.JSON
- var err error
- configJSON.Raw, err = json.Marshal(plugin.Config)
+ kongPlugin, err := createKongPlugin(plugin, username)
if err != nil {
return err
}
- kongPlugin.Config = configJSON
- file.KongPlugins = append(file.KongPlugins, kongPlugin)
-
- if kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] == "" {
- kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.ObjectMeta.Name
- } else {
- annotations := kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.ObjectMeta.Name
- kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] = annotations
+ if kongPlugin == nil {
+ continue
}
+ file.KongPlugins = append(file.KongPlugins, *kongPlugin)
+ addPluginToAnnotations(kongPlugin.ObjectMeta.Name, kongConsumer.ObjectMeta.Annotations)
}
file.KongConsumers = append(file.KongConsumers, kongConsumer)
@@ -73,258 +61,3 @@ func populateKICConsumers(content *file.Content, file *KICContent) error {
return nil
}
-
-func populateKICMTLSAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
- // iterate consumer.MTLSAuths and copy them into k8scorev1.Secret, then add them to kicContent.Secrets
- for _, mtlsAuth := range consumer.MTLSAuths {
- var secret k8scorev1.Secret
- secretName := "mtls-auth-" + *consumer.Username
- secret.TypeMeta.APIVersion = "v1"
- secret.TypeMeta.Kind = SecretKind
- secret.Type = "Opaque"
- secret.ObjectMeta.Name = calculateSlug(secretName)
- secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- secret.StringData = make(map[string]string)
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // for KIC v3, use the konghq.com/credential label to identify the credential type
- secret.ObjectMeta.Labels = map[string]string{"konghq.com/credential": "mtls-auth"}
- } else {
- // for KIC v2, use the kongCredType field to identify the credential type
- secret.StringData["kongCredType"] = "mtls-auth"
- }
-
- if mtlsAuth.SubjectName != nil {
- secret.StringData["subject_name"] = *mtlsAuth.SubjectName
- }
-
- if mtlsAuth.ID != nil {
- secret.StringData["id"] = *mtlsAuth.ID
- }
-
- if mtlsAuth.CACertificate != nil && mtlsAuth.CACertificate.Cert != nil {
- secret.StringData["ca_certificate"] = *mtlsAuth.CACertificate.Cert
- }
-
- // add the secret name to the kongConsumer.credentials
- kongConsumer.Credentials = append(kongConsumer.Credentials, secretName)
-
- file.Secrets = append(file.Secrets, secret)
- }
-}
-
-func populateKICACLGroupSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
- // iterate consumer.ACLGroups and copy them into k8scorev1.Secret, then add them to kicContent.Secrets
- for _, aclGroup := range consumer.ACLGroups {
- var secret k8scorev1.Secret
- secretName := "acl-group-" + *consumer.Username
- secret.TypeMeta.APIVersion = "v1"
- secret.TypeMeta.Kind = SecretKind
- secret.ObjectMeta.Name = calculateSlug(secretName)
- secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- secret.StringData = make(map[string]string)
-
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // for KIC v3, use the konghq.com/credential label to identify the credential type
- secret.ObjectMeta.Labels = map[string]string{"konghq.com/credential": "acl"}
- } else {
- // for KIC v2, use the kongCredType field to identify the credential type
- secret.StringData["kongCredType"] = "acl"
- }
-
- if aclGroup.Group != nil {
- secret.StringData["group"] = *aclGroup.Group
- }
-
- // add the secret name to the kongConsumer.credentials
- kongConsumer.Credentials = append(kongConsumer.Credentials, secretName)
-
- file.Secrets = append(file.Secrets, secret)
- }
-}
-
-func populateKICOAuth2CredSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
- // iterate consumer.OAuth2Creds and copy them into k8scorev1.Secret, then add them to kicContent.Secrets
- for _, oauth2Cred := range consumer.Oauth2Creds {
- var secret k8scorev1.Secret
- secretName := "oauth2cred-" + *consumer.Username
- secret.TypeMeta.APIVersion = "v1"
- secret.TypeMeta.Kind = SecretKind
- secret.ObjectMeta.Name = calculateSlug(secretName)
- secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- secret.StringData = make(map[string]string)
-
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // for KIC v3, use the konghq.com/credential label to identify the credential type
- secret.ObjectMeta.Labels = map[string]string{"konghq.com/credential": "oauth2"}
- } else {
- // for KIC v2, use the kongCredType field to identify the credential type
- secret.StringData["kongCredType"] = "oauth2"
- }
-
- if oauth2Cred.Name != nil {
- secret.StringData["name"] = *oauth2Cred.Name
- }
-
- if oauth2Cred.ClientID != nil {
- secret.StringData["client_id"] = *oauth2Cred.ClientID
- }
-
- if oauth2Cred.ClientSecret != nil {
- secret.StringData["client_secret"] = *oauth2Cred.ClientSecret
- }
-
- if oauth2Cred.ClientType != nil {
- secret.StringData["client_type"] = *oauth2Cred.ClientType
- }
-
- if oauth2Cred.HashSecret != nil {
- secret.StringData["hash_secret"] = strconv.FormatBool(*oauth2Cred.HashSecret)
- }
-
- // add the secret name to the kongConsumer.credentials
- kongConsumer.Credentials = append(kongConsumer.Credentials, secretName)
-
- file.Secrets = append(file.Secrets, secret)
- }
-}
-
-func populateKICBasicAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
- // iterate consumer.BasicAuths and copy them into k8scorev1.Secret, then add them to kicContent.Secrets
- for _, basicAuth := range consumer.BasicAuths {
- var secret k8scorev1.Secret
- secretName := "basic-auth-" + *consumer.Username
- secret.TypeMeta.APIVersion = "v1"
- secret.TypeMeta.Kind = SecretKind
- secret.ObjectMeta.Name = calculateSlug(secretName)
- secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- secret.StringData = make(map[string]string)
-
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // for KIC v3, use the konghq.com/credential label to identify the credential type
- secret.ObjectMeta.Labels = map[string]string{"konghq.com/credential": "basic-auth"}
- } else {
- // for KIC v2, use the kongCredType field to identify the credential type
- secret.StringData["kongCredType"] = "basic-auth"
- }
-
- if basicAuth.Username != nil {
- secret.StringData["username"] = *basicAuth.Username
- }
- if basicAuth.Password != nil {
- secret.StringData["password"] = *basicAuth.Password
- }
-
- // add the secret name to the kongConsumer.credentials
- kongConsumer.Credentials = append(kongConsumer.Credentials, secretName)
-
- file.Secrets = append(file.Secrets, secret)
- }
-}
-
-func populateKICJWTAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
- // iterate consumer.JWTAuths and copy them into k8scorev1.Secret, then add them to kicContent.Secrets
- for _, jwtAuth := range consumer.JWTAuths {
- var secret k8scorev1.Secret
- secretName := "jwt-auth-" + *consumer.Username
- secret.TypeMeta.APIVersion = "v1"
- secret.TypeMeta.Kind = SecretKind
- secret.ObjectMeta.Name = calculateSlug(secretName)
- secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- secret.StringData = make(map[string]string)
-
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // for KIC v3, use the konghq.com/credential label to identify the credential type
- secret.ObjectMeta.Labels = map[string]string{"konghq.com/credential": "jwt"}
- } else {
- // for KIC v2, use the kongCredType field to identify the credential type
- secret.StringData["kongCredType"] = "jwt"
- }
-
- // only do the following assignments if not null
- if jwtAuth.Key != nil {
- secret.StringData["key"] = *jwtAuth.Key
- }
-
- if jwtAuth.Algorithm != nil {
- secret.StringData["algorithm"] = *jwtAuth.Algorithm
- }
-
- if jwtAuth.RSAPublicKey != nil {
- secret.StringData["rsa_public_key"] = *jwtAuth.RSAPublicKey
- }
-
- if jwtAuth.Secret != nil {
- secret.StringData["secret"] = *jwtAuth.Secret
- }
-
- // add the secret name to the kongConsumer.credentials
- kongConsumer.Credentials = append(kongConsumer.Credentials, secretName)
-
- file.Secrets = append(file.Secrets, secret)
- }
-}
-
-func populateKICHMACSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
- // iterate consumer.HMACAuths and copy them into k8scorev1.Secret, then add them to kicContent.Secrets
- for _, hmacAuth := range consumer.HMACAuths {
- var secret k8scorev1.Secret
- secretName := "hmac-auth-" + *consumer.Username
- secret.TypeMeta.APIVersion = "v1"
- secret.TypeMeta.Kind = SecretKind
- secret.ObjectMeta.Name = calculateSlug(secretName)
- secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- secret.StringData = make(map[string]string)
-
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // for KIC v3, use the konghq.com/credential label to identify the credential type
- secret.ObjectMeta.Labels = map[string]string{"konghq.com/credential": "hmac-auth"}
- } else {
- // for KIC v2, use the kongCredType field to identify the credential type
- secret.StringData["kongCredType"] = "hmac-auth"
- }
-
- if hmacAuth.Username != nil {
- secret.StringData["username"] = *hmacAuth.Username
- }
-
- if hmacAuth.Secret != nil {
- secret.StringData["secret"] = *hmacAuth.Secret
- }
-
- // add the secret name to the kongConsumer.credentials
- kongConsumer.Credentials = append(kongConsumer.Credentials, secretName)
-
- file.Secrets = append(file.Secrets, secret)
- }
-}
-
-func populateKICKeyAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
- // iterate consumer.KeyAuths and copy them into k8scorev1.Secret, then add them to kicContent.Secrets
- // add the secret name to the kongConsumer.credentials
- for _, keyAuth := range consumer.KeyAuths {
- var secret k8scorev1.Secret
- secretName := "key-auth-" + *consumer.Username
- secret.TypeMeta.APIVersion = "v1"
- secret.TypeMeta.Kind = SecretKind
- secret.ObjectMeta.Name = calculateSlug(secretName)
- secret.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- secret.StringData = make(map[string]string)
-
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // for KIC v3, use the konghq.com/credential label to identify the credential type
- secret.ObjectMeta.Labels = map[string]string{"konghq.com/credential": "key-auth"}
- } else {
- // for KIC v2, use the kongCredType field to identify the credential type
- secret.StringData["kongCredType"] = "key-auth"
- }
-
- if keyAuth.Key != nil {
- secret.StringData["key"] = *keyAuth.Key
- }
-
- kongConsumer.Credentials = append(kongConsumer.Credentials, secretName)
-
- file.Secrets = append(file.Secrets, secret)
-
- }
-}
diff --git a/kong2kic/consumer_credentials.go b/kong2kic/consumer_credentials.go
new file mode 100644
index 000000000..55760f019
--- /dev/null
+++ b/kong2kic/consumer_credentials.go
@@ -0,0 +1,137 @@
+package kong2kic
+
+import (
+ "strconv"
+
+ "github.com/kong/go-database-reconciler/pkg/file"
+ kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
+ k8scorev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// Helper function to create credential secrets
+func createCredentialSecret(consumerUsername, credentialType string, dataFields map[string]*string) k8scorev1.Secret {
+ secretName := credentialType + "-" + consumerUsername
+ stringData := make(map[string]string)
+ labels := map[string]string{}
+ if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
+ labels["konghq.com/credential"] = credentialType
+ } else {
+ stringData["kongCredType"] = credentialType
+ }
+
+ // Add the data fields to stringData
+ for key, value := range dataFields {
+ if value != nil {
+ stringData[key] = *value
+ }
+ }
+
+ return k8scorev1.Secret{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "v1",
+ Kind: SecretKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(secretName),
+ Annotations: map[string]string{IngressClass: ClassName},
+ Labels: labels,
+ },
+ Type: "Opaque",
+ StringData: stringData,
+ }
+}
+
+// Functions to populate different credential types
+func populateKICKeyAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
+ for _, keyAuth := range consumer.KeyAuths {
+ dataFields := map[string]*string{
+ "key": keyAuth.Key,
+ }
+ secret := createCredentialSecret(*consumer.Username, "key-auth", dataFields)
+ kongConsumer.Credentials = append(kongConsumer.Credentials, secret.ObjectMeta.Name)
+ file.Secrets = append(file.Secrets, secret)
+ }
+}
+
+func populateKICHMACSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
+ for _, hmacAuth := range consumer.HMACAuths {
+ dataFields := map[string]*string{
+ "username": hmacAuth.Username,
+ "secret": hmacAuth.Secret,
+ }
+ secret := createCredentialSecret(*consumer.Username, "hmac-auth", dataFields)
+ kongConsumer.Credentials = append(kongConsumer.Credentials, secret.ObjectMeta.Name)
+ file.Secrets = append(file.Secrets, secret)
+ }
+}
+
+func populateKICJWTAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
+ for _, jwtAuth := range consumer.JWTAuths {
+ dataFields := map[string]*string{
+ "key": jwtAuth.Key,
+ "algorithm": jwtAuth.Algorithm,
+ "rsa_public_key": jwtAuth.RSAPublicKey,
+ "secret": jwtAuth.Secret,
+ }
+ secret := createCredentialSecret(*consumer.Username, "jwt", dataFields)
+ kongConsumer.Credentials = append(kongConsumer.Credentials, secret.ObjectMeta.Name)
+ file.Secrets = append(file.Secrets, secret)
+ }
+}
+
+func populateKICBasicAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
+ for _, basicAuth := range consumer.BasicAuths {
+ dataFields := map[string]*string{
+ "username": basicAuth.Username,
+ "password": basicAuth.Password,
+ }
+ secret := createCredentialSecret(*consumer.Username, "basic-auth", dataFields)
+ kongConsumer.Credentials = append(kongConsumer.Credentials, secret.ObjectMeta.Name)
+ file.Secrets = append(file.Secrets, secret)
+ }
+}
+
+func populateKICOAuth2CredSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
+ for _, oauth2Cred := range consumer.Oauth2Creds {
+ dataFields := map[string]*string{
+ "name": oauth2Cred.Name,
+ "client_id": oauth2Cred.ClientID,
+ "client_secret": oauth2Cred.ClientSecret,
+ "client_type": oauth2Cred.ClientType,
+ }
+ if oauth2Cred.HashSecret != nil {
+ hashSecretStr := strconv.FormatBool(*oauth2Cred.HashSecret)
+ dataFields["hash_secret"] = &hashSecretStr
+ }
+ secret := createCredentialSecret(*consumer.Username, "oauth2", dataFields)
+ kongConsumer.Credentials = append(kongConsumer.Credentials, secret.ObjectMeta.Name)
+ file.Secrets = append(file.Secrets, secret)
+ }
+}
+
+func populateKICACLGroupSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
+ for _, aclGroup := range consumer.ACLGroups {
+ dataFields := map[string]*string{
+ "group": aclGroup.Group,
+ }
+ secret := createCredentialSecret(*consumer.Username, "acl", dataFields)
+ kongConsumer.Credentials = append(kongConsumer.Credentials, secret.ObjectMeta.Name)
+ file.Secrets = append(file.Secrets, secret)
+ }
+}
+
+func populateKICMTLSAuthSecrets(consumer *file.FConsumer, kongConsumer *kicv1.KongConsumer, file *KICContent) {
+ for _, mtlsAuth := range consumer.MTLSAuths {
+ dataFields := map[string]*string{
+ "subject_name": mtlsAuth.SubjectName,
+ "id": mtlsAuth.ID,
+ }
+ if mtlsAuth.CACertificate != nil && mtlsAuth.CACertificate.Cert != nil {
+ dataFields["ca_certificate"] = mtlsAuth.CACertificate.Cert
+ }
+ secret := createCredentialSecret(*consumer.Username, "mtls-auth", dataFields)
+ kongConsumer.Credentials = append(kongConsumer.Credentials, secret.ObjectMeta.Name)
+ file.Secrets = append(file.Secrets, secret)
+ }
+}
diff --git a/kong2kic/consumer_group.go b/kong2kic/consumer_group.go
index a252a1861..a39f30666 100644
--- a/kong2kic/consumer_group.go
+++ b/kong2kic/consumer_group.go
@@ -5,76 +5,94 @@ import (
"log"
"github.com/kong/go-database-reconciler/pkg/file"
+ "github.com/kong/go-kong/kong"
kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
kicv1beta1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1beta1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
+// Helper function to populate consumer group plugins
+func createConsumerGroupKongPlugin(plugin *kong.ConsumerGroupPlugin, ownerName string) (*kicv1.KongPlugin, error) {
+ if plugin.Name == nil {
+ log.Println("Plugin name is empty. Please provide a name for the plugin.")
+ return nil, nil
+ }
+ pluginName := *plugin.Name
+ kongPlugin := &kicv1.KongPlugin{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "configuration.konghq.com/v1",
+ Kind: "KongPlugin",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(ownerName + "-" + pluginName),
+ Annotations: map[string]string{IngressClass: ClassName},
+ },
+ PluginName: pluginName,
+ }
+
+ // Transform the plugin config
+ configJSON, err := json.Marshal(plugin.Config)
+ if err != nil {
+ return nil, err
+ }
+ kongPlugin.Config = apiextensionsv1.JSON{
+ Raw: configJSON,
+ }
+
+ return kongPlugin, nil
+}
+
func populateKICConsumerGroups(content *file.Content, kicContent *KICContent) error {
- // iterate over the consumer groups and create a KongConsumerGroup for each one
for _, consumerGroup := range content.ConsumerGroups {
- var kongConsumerGroup kicv1beta1.KongConsumerGroup
- kongConsumerGroup.APIVersion = "configuration.konghq.com/v1beta1"
- kongConsumerGroup.Kind = "KongConsumerGroup"
- if consumerGroup.Name != nil {
- kongConsumerGroup.ObjectMeta.Name = calculateSlug(*consumerGroup.Name)
- } else {
- log.Println("Consumer group name is empty. This is not recommended." +
- "Please, provide a name for the consumer group before generating Kong Ingress Controller manifests.")
+ if consumerGroup.Name == nil {
+ log.Println("Consumer group name is empty. Please provide a name for the consumer group.")
continue
}
- kongConsumerGroup.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- kongConsumerGroup.Name = *consumerGroup.Name
+ groupName := *consumerGroup.Name
+
+ kongConsumerGroup := kicv1beta1.KongConsumerGroup{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "configuration.konghq.com/v1beta1",
+ Kind: "KongConsumerGroup",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(groupName),
+ Annotations: map[string]string{IngressClass: ClassName},
+ },
+ }
+
+ // Add tags to annotations
+ addTagsToAnnotations(consumerGroup.Tags, kongConsumerGroup.ObjectMeta.Annotations)
- // Iterate over the consumers in consumerGroup and
- // find the KongConsumer with the same username in kicContent.KongConsumers
- // and add it to the KongConsumerGroup
+ // Update the ConsumerGroups field of the KongConsumers
for _, consumer := range consumerGroup.Consumers {
+ if consumer.Username == nil {
+ log.Println("Consumer username is empty. Please provide a username for the consumer.")
+ continue
+ }
+ username := *consumer.Username
for idx := range kicContent.KongConsumers {
- if kicContent.KongConsumers[idx].Username == *consumer.Username {
- if kicContent.KongConsumers[idx].ConsumerGroups == nil {
- kicContent.KongConsumers[idx].ConsumerGroups = make([]string, 0)
- }
- consumerGroups := append(kicContent.KongConsumers[idx].ConsumerGroups, *consumerGroup.Name)
- kicContent.KongConsumers[idx].ConsumerGroups = consumerGroups
+ if kicContent.KongConsumers[idx].Username == username {
+ kicContent.KongConsumers[idx].ConsumerGroups = append(kicContent.KongConsumers[idx].ConsumerGroups, groupName)
}
}
}
- // for each consumerGroup plugin, create a KongPlugin and a plugin annotation in the kongConsumerGroup
- // to link the plugin. Consumer group plugins are "global plugins" with a consumer_group property
- for _, plugin := range content.Plugins {
- if plugin.ConsumerGroup.ID != nil && *plugin.ConsumerGroup.ID == *consumerGroup.Name {
- var kongPlugin kicv1.KongPlugin
- kongPlugin.APIVersion = KICAPIVersion
- kongPlugin.Kind = KongPluginKind
- kongPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- if plugin.Name != nil {
- kongPlugin.PluginName = *consumerGroup.Name + "-" + *plugin.Name
- kongPlugin.ObjectMeta.Name = calculateSlug(*consumerGroup.Name + "-" + *plugin.Name)
- } else {
- log.Println("Plugin name is empty. This is not recommended." +
- "Please, provide a name for the plugin before generating Kong Ingress Controller manifests.")
- continue
- }
+ // Handle plugins
+ for _, plugin := range consumerGroup.Plugins {
+ kongPlugin, err := createConsumerGroupKongPlugin(plugin, groupName)
+ if err != nil {
+ return err
+ }
+ if kongPlugin == nil {
+ continue
+ }
- // transform the plugin config from map[string]interface{} to apiextensionsv1.JSON
- var configJSON apiextensionsv1.JSON
- var err error
- configJSON.Raw, err = json.Marshal(plugin.Config)
- if err != nil {
- return err
- }
- kongPlugin.Config = configJSON
- kicContent.KongPlugins = append(kicContent.KongPlugins, kongPlugin)
+ kicContent.KongPlugins = append(kicContent.KongPlugins, *kongPlugin)
- if kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] == "" {
- kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.ObjectMeta.Name
- } else {
- annotations := kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.ObjectMeta.Name
- kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] = annotations
- }
- }
+ // Add plugin to kongConsumerGroup annotations
+ addPluginToAnnotations(kongPlugin.ObjectMeta.Name, kongConsumerGroup.ObjectMeta.Annotations)
}
kicContent.KongConsumerGroups = append(kicContent.KongConsumerGroups, kongConsumerGroup)
diff --git a/kong2kic/global_plugin.go b/kong2kic/global_plugin.go
index 5c7b7e5cc..b5ab3fa39 100644
--- a/kong2kic/global_plugin.go
+++ b/kong2kic/global_plugin.go
@@ -3,8 +3,10 @@ package kong2kic
import (
"encoding/json"
"log"
+ "strings"
"github.com/kong/go-database-reconciler/pkg/file"
+ "github.com/kong/go-kong/kong"
kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)
@@ -19,19 +21,53 @@ func populateKICKongClusterPlugins(content *file.Content, file *KICContent) erro
if plugin.ConsumerGroup != nil {
continue
}
- var kongPlugin kicv1.KongClusterPlugin
- kongPlugin.APIVersion = KICAPIVersion
- kongPlugin.Kind = "KongClusterPlugin"
- kongPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
+ var kongClusterPlugin kicv1.KongClusterPlugin
+ kongClusterPlugin.APIVersion = KICAPIVersion
+ kongClusterPlugin.Kind = "KongClusterPlugin"
+ kongClusterPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
if plugin.Name != nil {
- kongPlugin.PluginName = *plugin.Name
- kongPlugin.ObjectMeta.Name = calculateSlug(*plugin.Name)
+ kongClusterPlugin.PluginName = *plugin.Name
+ kongClusterPlugin.ObjectMeta.Name = calculateSlug(*plugin.Name)
} else {
log.Println("Global Plugin name is empty. This is not recommended." +
"Please, provide a name for the plugin before generating Kong Ingress Controller manifests.")
continue
}
+ // populate enabled, runon, ordering and protocols
+ if plugin.Enabled != nil {
+ kongClusterPlugin.Disabled = !*plugin.Enabled
+ }
+ if plugin.RunOn != nil {
+ kongClusterPlugin.RunOn = *plugin.RunOn
+ }
+ if plugin.Ordering != nil {
+ kongClusterPlugin.Ordering = &kong.PluginOrdering{
+ Before: plugin.Ordering.Before,
+ After: plugin.Ordering.After,
+ }
+ }
+ if plugin.Protocols != nil {
+ protocols := make([]string, len(plugin.Protocols))
+ for i, protocol := range plugin.Protocols {
+ if protocol != nil {
+ protocols[i] = *protocol
+ }
+ }
+ kongClusterPlugin.Protocols = kicv1.StringsToKongProtocols(protocols)
+ }
+
+ // add konghq.com/tags annotation if plugin.Tags is not nil
+ if plugin.Tags != nil {
+ var tags []string
+ for _, tag := range plugin.Tags {
+ if tag != nil {
+ tags = append(tags, *tag)
+ }
+ }
+ kongClusterPlugin.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
+ }
+
// transform the plugin config from map[string]interface{} to apiextensionsv1.JSON
var configJSON apiextensionsv1.JSON
var err error
@@ -39,8 +75,8 @@ func populateKICKongClusterPlugins(content *file.Content, file *KICContent) erro
if err != nil {
return err
}
- kongPlugin.Config = configJSON
- file.KongClusterPlugins = append(file.KongClusterPlugins, kongPlugin)
+ kongClusterPlugin.Config = configJSON
+ file.KongClusterPlugins = append(file.KongClusterPlugins, kongClusterPlugin)
}
return nil
}
diff --git a/kong2kic/kong2kic_test.go b/kong2kic/kong2kic_test.go
index fc5031a8f..a7ca821b6 100644
--- a/kong2kic/kong2kic_test.go
+++ b/kong2kic/kong2kic_test.go
@@ -1,40 +1,71 @@
package kong2kic
import (
+ "bytes"
+ "context"
+ "errors"
+ "io"
+ "net/http"
"os"
+ "path/filepath"
+ "regexp"
"strings"
+ "sync"
"testing"
+ "time"
"github.com/kong/go-database-reconciler/pkg/file"
- "github.com/stretchr/testify/assert"
+ "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/kong"
+ "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/metallb"
+ environment "github.com/kong/kubernetes-testing-framework/pkg/environments"
"github.com/stretchr/testify/require"
+ apiv1 "k8s.io/api/core/v1"
+ apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+ "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/util/yaml"
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/rest"
)
var baseLocation = "testdata/"
-func fixJSONstream(input string) string {
- // this is a stream of json files, must update to an actual json array
- return "[" + strings.Replace(input, "}{", "},{", -1) + "]"
+// Helper function to read and fix JSON stream
+func readAndFixJSONStream(filename string) (string, error) {
+ content, err := os.ReadFile(filepath.Join(baseLocation, filename))
+ if err != nil {
+ return "", err
+ }
+ // Update to an actual JSON array
+ fixedContent := "[" + strings.ReplaceAll(string(content), "}{", "},{") + "]"
+ return fixedContent, nil
}
+// Helper function to compare file content
func compareFileContent(t *testing.T, expectedFilename string, actualContent []byte) {
- expected, err := os.ReadFile(baseLocation + expectedFilename)
- if err != nil {
- assert.Fail(t, err.Error())
- }
+ expectedPath := filepath.Join(baseLocation, expectedFilename)
+ expectedContent, err := os.ReadFile(expectedPath)
+ require.NoError(t, err)
- actualFilename := baseLocation + strings.Replace(expectedFilename, "-expected.", "-actual.", 1)
- os.WriteFile(actualFilename, actualContent, 0o600)
+ // Write actual content to file for debugging
+ actualFilename := strings.Replace(expectedFilename, "-expected.", "-actual.", 1)
+ actualPath := filepath.Join(baseLocation, actualFilename)
+ err = os.WriteFile(actualPath, actualContent, 0o600)
+ require.NoError(t, err)
if strings.HasSuffix(expectedFilename, ".json") {
- // this is a stream of json files, must update to an actual json array
- require.JSONEq(t, fixJSONstream(string(expected)), fixJSONstream(string(actualContent)))
+ expectedJSON, err := readAndFixJSONStream(expectedFilename)
+ require.NoError(t, err)
+ actualJSON := "[" + strings.ReplaceAll(string(actualContent), "}{", "},{") + "]"
+ require.JSONEq(t, expectedJSON, actualJSON)
} else {
- require.YAMLEq(t, string(expected), string(actualContent))
+ require.YAMLEq(t, string(expectedContent), string(actualContent))
}
}
-func Test_convertKongGatewayToIngress(t *testing.T) {
+func Test_convertKongGatewayToKIC(t *testing.T) {
tests := []struct {
name string
inputFilename string
@@ -43,81 +74,437 @@ func Test_convertKongGatewayToIngress(t *testing.T) {
wantErr bool
}{
{
- name: "Kong to KIC: kic v3.x Gateway API, yaml",
- inputFilename: "input.yaml",
- outputFilename: "kicv3_gateway/output-expected.yaml",
+ // Service does not depend on v2 vs v3, or Gateway vs Ingress
+ name: "Kong to KIC: Service",
+ inputFilename: "service-input.yaml",
+ outputFilename: "service-output-expected.yaml",
builderType: KICV3GATEWAY,
wantErr: false,
},
{
- name: "Kong to KIC: kic v3.x Gateway API, json",
- inputFilename: "input.yaml",
- outputFilename: "kicv3_gateway/output-expected.json",
+ // Route to HTTPRoute, Gateway API and KIC v3.
+ // In KIC v3 apiVersion: gateway.networking.k8s.io/v1
+ name: "Kong to KIC: Route API GW, KIC v3",
+ inputFilename: "route-input.yaml",
+ outputFilename: "route-gw-v3-output-expected.yaml",
builderType: KICV3GATEWAY,
wantErr: false,
},
{
- name: "Kong to KIC: kic v3.x Ingress API, yaml",
- inputFilename: "input.yaml",
- outputFilename: "kicv3_ingress/output-expected.yaml",
- builderType: KICV3INGRESS,
+ // Route to HTTPRoute, Gateway API and KIC v2
+ // In KIC v2 apiVersion: gateway.networking.k8s.io/v1beta1
+ name: "Kong to KIC: Route API GW, KIC v2",
+ inputFilename: "route-input.yaml",
+ outputFilename: "route-gw-v2-output-expected.yaml",
+ builderType: KICV2GATEWAY,
wantErr: false,
},
{
- name: "Kong to KIC: kic v3.x Ingress API, json",
- inputFilename: "input.yaml",
- outputFilename: "kicv3_ingress/output-expected.json",
+ // Route to Ingress, Ingress API. Output does not depend on KIC v2 vs v3
+ name: "Kong to KIC: Route Ingress API",
+ inputFilename: "route-input.yaml",
+ outputFilename: "route-ingress-output-expected.yaml",
builderType: KICV3INGRESS,
wantErr: false,
},
{
- name: "Kong to KIC: kic v2.x Gateway API, yaml",
- inputFilename: "input.yaml",
- outputFilename: "kicv2_gateway/output-expected.yaml",
+ // Upstream to KongIngress for KIC v2
+ name: "Kong to KIC: Upstream KIC v2",
+ inputFilename: "upstream-input.yaml",
+ outputFilename: "upstream-v2-output-expected.yaml",
builderType: KICV2GATEWAY,
wantErr: false,
},
{
- name: "Kong to KIC: kic v2.x Gateway API, json",
- inputFilename: "input.yaml",
- outputFilename: "kicv2_gateway/output-expected.json",
+ // Upstream to KongUpstreamPolicy for KIC v3
+ name: "Kong to KIC: Upstream KIC v3",
+ inputFilename: "upstream-input.yaml",
+ outputFilename: "upstream-v3-output-expected.yaml",
+ builderType: KICV3GATEWAY,
+ wantErr: false,
+ },
+ {
+ // Global Plugin to KongClusterPlugin. Output does not depend on KIC v2 vs v3
+ name: "Kong to KIC: Global Plugin",
+ inputFilename: "global-plugin-input.yaml",
+ outputFilename: "global-plugin-output-expected.yaml",
+ builderType: KICV3GATEWAY,
+ wantErr: false,
+ },
+ {
+ // Consumer to KongConsumer. Output depends on KIC v2 vs v3.
+ // KIC v2 uses kongCredType for credential type, KIC v3 uses labels
+ name: "Kong to KIC: Consumer KIC v2",
+ inputFilename: "consumer-input.yaml",
+ outputFilename: "consumer-v2-output-expected.yaml",
builderType: KICV2GATEWAY,
wantErr: false,
},
{
- name: "Kong to KIC: kic v2.x Ingress API, yaml",
- inputFilename: "input.yaml",
- outputFilename: "kicv2_ingress/output-expected.yaml",
- builderType: KICV2INGRESS,
+ // Consumer to KongConsumer. Output depends on KIC v2 vs v3.
+ // KIC v2 uses kongCredType for credential type, KIC v3 uses labels
+ name: "Kong to KIC: Consumer KIC v3",
+ inputFilename: "consumer-input.yaml",
+ outputFilename: "consumer-v3-output-expected.yaml",
+ builderType: KICV3GATEWAY,
wantErr: false,
},
{
- name: "Kong to KIC: kic v2.x Ingress API, json",
- inputFilename: "input.yaml",
- outputFilename: "kicv2_ingress/output-expected.json",
- builderType: KICV2INGRESS,
+ // Consumer Group to KongConsumerGroup. Output does not depend on KIC v2 vs v3
+ name: "Kong to KIC: ConsumerGroup",
+ inputFilename: "consumer-group-input.yaml",
+ outputFilename: "consumer-group-output-expected.yaml",
+ builderType: KICV3GATEWAY,
+ wantErr: false,
+ },
+ {
+ // Certificate to Secret type: kubernetes.io/tls.
+ // Output does not depend on KIC v2 vs v3
+ name: "Kong to KIC: Certificate",
+ inputFilename: "certificate-input.yaml",
+ outputFilename: "certificate-output-expected.yaml",
+ builderType: KICV3GATEWAY,
+ wantErr: false,
+ },
+ {
+ // CA Certificate to Secret type: Opaque.
+ // Output does not depend on KIC v2 vs v3
+ name: "Kong to KIC: CA Certificate",
+ inputFilename: "ca-certificate-input.yaml",
+ outputFilename: "ca-certificate-output-expected.yaml",
+ builderType: KICV3GATEWAY,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- inputContent, err := file.GetContentFromFiles([]string{baseLocation + tt.inputFilename}, false)
- if err != nil {
- assert.Fail(t, err.Error())
- }
+ inputPath := filepath.Join(baseLocation, tt.inputFilename)
+ inputContent, err := file.GetContentFromFiles([]string{inputPath}, false)
+ require.NoError(t, err)
- var output []byte
+ outputFormat := file.YAML
if strings.HasSuffix(tt.outputFilename, ".json") {
- output, err = MarshalKongToKIC(inputContent, tt.builderType, file.JSON)
- } else {
- output, err = MarshalKongToKIC(inputContent, tt.builderType, file.YAML)
+ outputFormat = file.JSON
}
+ output, err := MarshalKongToKIC(inputContent, tt.builderType, outputFormat)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("MarshalKongToKIC() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
if err == nil {
compareFileContent(t, tt.outputFilename, output)
- } else if (err != nil) != tt.wantErr {
- t.Errorf("KongToKIC() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
+
+func Test_deployManifests(t *testing.T) {
+ versions := []string{"2.12", "3.0", "3.1", "3.2", "3.3"}
+ for _, version := range versions {
+ t.Run("KIC Version "+version, func(t *testing.T) {
+ t.Parallel()
+ ctx := context.Background()
+
+ // Configure the testing environment with the specified KIC version
+ env, kongAddon, err := setupTestingEnvironmentWithVersion(ctx, version)
+ require.NoError(t, err)
+ defer teardownEnvironment(ctx, t, env)
+
+ t.Log("waiting for the test environment to be ready for use")
+ require.NoError(t, <-env.WaitForReady(ctx))
+
+ t.Log("verifying the test environment becomes ready for use")
+ waitForObjects, ready, err := env.Ready(ctx)
+ require.NoError(t, err)
+ require.Empty(t, waitForObjects)
+ require.True(t, ready)
+
+ t.Log("verifying the kong proxy is returning its default 404 response")
+ proxyURL, err := getKongProxyURL(ctx, env)
+ require.NoError(t, err)
+ verifyKongProxyResponse(t, proxyURL)
+
+ t.Log("verifying that the kong addon deployed both proxy and controller")
+ verifyKongDeployment(ctx, t, env, kongAddon)
+
+ config := env.Cluster().Config()
+
+ t.Log("deploying the Gateway API CRDs")
+ clientset, err := deployGatewayAPICRDs(t, config)
+ require.NoError(t, err)
+
+ t.Log("obtaining the ServerPreferredResources from the cluster")
+ kindToResource, err := getKindToResourceMap(clientset)
+ require.NoError(t, err)
+
+ t.Log("creating a dynamic client for Kubernetes resources")
+ dynamicClient, err := dynamic.NewForConfig(config)
+ require.NoError(t, err)
+
+ t.Log("deploying manifests to the cluster")
+ err = deployManifestsToClusterForVersion(t, dynamicClient, kindToResource, version)
+ require.NoError(t, err)
+ })
+ }
+}
+
+// Helper function to set up the testing environment with a specific KIC version
+func setupTestingEnvironmentWithVersion(
+ ctx context.Context,
+ kicVersion string,
+) (environment.Environment, *kong.Addon, error) {
+ builder := environment.NewBuilder()
+ kongAddonBuilder := kong.NewBuilder().
+ WithControllerImage("kong/kubernetes-ingress-controller", kicVersion).
+ WithProxyImage("kong", "3.4") // Adjust proxy image if needed
+
+ kongAddon := kongAddonBuilder.Build()
+ env, err := builder.WithAddons(metallb.New(), kongAddon).Build(ctx)
+ if err != nil {
+ return nil, nil, err
+ }
+ return env, kongAddon, nil
+}
+
+// Mutex to avoid race condition on ~/.kube/config file
+var teardownMutex sync.Mutex
+
+func teardownEnvironment(ctx context.Context, t *testing.T, env environment.Environment) {
+ // Lock the mutex to ensure only one teardown process at a time
+ teardownMutex.Lock()
+ defer teardownMutex.Unlock()
+
+ t.Logf("cleaning up environment %s and cluster %s", env.Name(), env.Cluster().Name())
+ require.NoError(t, env.Cleanup(ctx))
+}
+
+// Helper function to get Kong proxy URL
+func getKongProxyURL(ctx context.Context, env environment.Environment) (string, error) {
+ kongAon, err := env.Cluster().GetAddon("kong")
+ if err != nil {
+ return "", err
+ }
+ kongAddonRaw, ok := kongAon.(*kong.Addon)
+ if !ok {
+ return "", errors.New("failed to cast kong addon")
+ }
+ proxyURL, err := kongAddonRaw.ProxyHTTPURL(ctx, env.Cluster())
+ if err != nil {
+ return "", err
+ }
+ return proxyURL.String(), nil
+}
+
+// Helper function to verify Kong proxy response
+func verifyKongProxyResponse(t *testing.T, proxyURL string) {
+ httpc := http.Client{Timeout: time.Second * 10}
+ require.Eventually(t, func() bool {
+ resp, err := httpc.Get(proxyURL)
+ if err != nil {
+ return false
+ }
+ defer resp.Body.Close()
+ return resp.StatusCode == http.StatusNotFound
+ }, time.Minute*3, time.Second)
+}
+
+// Helper function to verify Kong deployment
+func verifyKongDeployment(ctx context.Context, t *testing.T, env environment.Environment, kongAddon *kong.Addon) {
+ client := env.Cluster().Client()
+ appsV1 := client.AppsV1()
+ deployments := appsV1.Deployments(kongAddon.Namespace())
+ kongDeployment, err := deployments.Get(ctx, "ingress-controller-kong", metav1.GetOptions{})
+ require.NoError(t, err)
+ require.Len(t, kongDeployment.Spec.Template.Spec.Containers, 2)
+ require.Equal(t, "ingress-controller", kongDeployment.Spec.Template.Spec.Containers[0].Name)
+ require.Equal(t, "proxy", kongDeployment.Spec.Template.Spec.Containers[1].Name)
+}
+
+// Helper function to deploy Gateway API CRDs
+func deployGatewayAPICRDs(t *testing.T, config *rest.Config) (*clientset.Clientset, error) {
+ clientset, err := clientset.NewForConfig(config)
+ if err != nil {
+ return nil, err
+ }
+
+ gatewayAPICrdPath := filepath.Join("testdata", "gateway-api-crd.yaml")
+ gatewayAPICrdFile, err := os.ReadFile(gatewayAPICrdPath)
+ if err != nil {
+ return nil, err
+ }
+
+ // Split the YAML file into individual documents.
+ yamlDocs := regexp.MustCompile(`(?m)^---\s*$`).Split(string(gatewayAPICrdFile), -1)
+
+ for _, doc := range yamlDocs {
+ if strings.TrimSpace(doc) == "" {
+ continue
+ }
+
+ dec := yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(doc)), 4096)
+ var crd apiextensionsv1.CustomResourceDefinition
+ err := dec.Decode(&crd)
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = clientset.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), &crd, metav1.CreateOptions{})
+ if err != nil {
+ return nil, err
+ }
+ t.Logf("created CRD: %s", crd.Name)
+ }
+
+ // Wait for CRDs to be available
+ time.Sleep(2 * time.Second)
+ return clientset, nil
+}
+
+// Helper function to get Kind to Resource mapping
+func getKindToResourceMap(clientset *clientset.Clientset) (map[string]string, error) {
+ kindToResource := make(map[string]string)
+ groups, err := clientset.Discovery().ServerPreferredResources()
+ if err != nil {
+ return nil, err
+ }
+ for _, group := range groups {
+ for _, resource := range group.APIResources {
+ kindToResource[resource.Kind] = resource.Name
+ }
+ }
+ return kindToResource, nil
+}
+
+// Helper function to deploy manifests to the cluster
+func deployManifestsToClusterForVersion(
+ t *testing.T,
+ dynamicClient dynamic.Interface,
+ kindToResource map[string]string,
+ version string,
+) error {
+ files, err := os.ReadDir("testdata/")
+ if err != nil {
+ return err
+ }
+
+ for _, file := range files {
+ filename := file.Name()
+ if !strings.HasSuffix(filename, "output-expected.yaml") {
+ continue
+ }
+ // Skip files based on version
+ if version == "2.12" && strings.Contains(filename, "-v3-") {
+ continue
+ }
+ if version != "2.12" && strings.Contains(filename, "-v2-") {
+ continue
+ }
+ content, err := os.ReadFile(filepath.Join("testdata", filename))
+ if err != nil {
+ return err
+ }
+ t.Logf("DEPLOYING MANIFEST: %s for KIC version %s", filename, version)
+ err = deployManifestToCluster(t, content, kindToResource, dynamicClient)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Simplify the deployManifestToCluster function
+func deployManifestToCluster(
+ t *testing.T,
+ manifest []byte,
+ kindToResource map[string]string,
+ dynamicClient dynamic.Interface,
+) error {
+ decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(manifest), 4096)
+ var objectsToDelete []ObjectToDelete
+
+ for {
+ var rawObj unstructured.Unstructured
+ if err := decoder.Decode(&rawObj); err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ return err
+ }
+
+ gvr, err := getGroupVersionResource(&rawObj, kindToResource)
+ if err != nil {
+ return err
+ }
+
+ setNamespaceIfNeeded(&rawObj)
+
+ _, err = dynamicClient.Resource(gvr).
+ Namespace(rawObj.GetNamespace()).
+ Create(context.TODO(), &rawObj, metav1.CreateOptions{})
+ if err != nil {
+ return err
+ }
+ t.Logf("created object: %s of Kind: %s in Namespace: %s", rawObj.GetName(), rawObj.GetKind(), rawObj.GetNamespace())
+ objectsToDelete = append(objectsToDelete, ObjectToDelete{object: rawObj, gvr: gvr})
+ }
+
+ // Clean up created objects
+ for _, obj := range objectsToDelete {
+ err := dynamicClient.Resource(obj.gvr).
+ Namespace(obj.object.GetNamespace()).
+ Delete(context.TODO(), obj.object.GetName(), metav1.DeleteOptions{})
+ if err != nil {
+ return err
+ }
+ t.Logf("deleted object: %s of Kind: %s in Namespace: %s",
+ obj.object.GetName(),
+ obj.object.GetKind(),
+ obj.object.GetNamespace())
+ }
+ return nil
+}
+
+// Helper function to get GroupVersionResource from an unstructured object
+func getGroupVersionResource(
+ obj *unstructured.Unstructured,
+ kindToResource map[string]string,
+) (schema.GroupVersionResource, error) {
+ apiVersion := obj.GetAPIVersion()
+ kind := obj.GetKind()
+ resource, exists := kindToResource[kind]
+ if !exists {
+ return schema.GroupVersionResource{}, errors.New("resource not found for kind: " + kind)
+ }
+
+ parts := strings.Split(apiVersion, "/")
+ if len(parts) == 2 {
+ return schema.GroupVersionResource{
+ Group: parts[0],
+ Version: parts[1],
+ Resource: resource,
+ }, nil
+ } else if len(parts) == 1 {
+ return schema.GroupVersionResource{
+ Group: "",
+ Version: parts[0],
+ Resource: resource,
+ }, nil
+ }
+ return schema.GroupVersionResource{}, errors.New("invalid apiVersion: " + apiVersion)
+}
+
+// Helper function to set namespace if needed
+func setNamespaceIfNeeded(obj *unstructured.Unstructured) {
+ if obj.GetKind() == "KongClusterPlugin" {
+ obj.SetNamespace(apiv1.NamespaceAll)
+ } else if obj.GetNamespace() == "" {
+ obj.SetNamespace(apiv1.NamespaceDefault)
+ }
+}
+
+// Type definition for objects to delete
+type ObjectToDelete struct {
+ object unstructured.Unstructured
+ gvr schema.GroupVersionResource
+}
diff --git a/kong2kic/route.go b/kong2kic/route.go
index f9e797dca..0c014c7ea 100644
--- a/kong2kic/route.go
+++ b/kong2kic/route.go
@@ -3,229 +3,174 @@ package kong2kic
import (
"encoding/json"
"log"
- "sort"
"strconv"
"strings"
"github.com/kong/go-database-reconciler/pkg/file"
+ "github.com/kong/go-kong/kong"
kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
k8snetv1 "k8s.io/api/networking/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
- k8sgwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
-// Convert route to Ingress (Ingress API)
-func populateKICIngressesWithAnnotations(content *file.Content, kicContent *KICContent) error {
- // For each route under each service create one ingress.
- // If the route has multiple hosts, create the relevant host declarations in the ingress
- // and under each hosts create a declaration for each path in the route.
- // If the route has no hosts, create a declaration in the ingress for each path in the route.
- // Map additional fields in the route to annotations in the ingress.
- // If the route has plugins, create a KongPlugin for each one and add an annotation to the ingress
- // to link the plugin to it.
- for _, service := range content.Services {
- for _, route := range service.Routes {
- // save all ingresses we create for this route so we can then
- // assign them the plugins defined for the route
- var (
- k8sIngress k8snetv1.Ingress
- pathTypeImplSpecific = k8snetv1.PathTypeImplementationSpecific
- )
-
- k8sIngress.TypeMeta.APIVersion = "networking.k8s.io/v1"
- k8sIngress.TypeMeta.Kind = "Ingress"
- if service.Name != nil && route.Name != nil {
- k8sIngress.ObjectMeta.Name = calculateSlug(*service.Name + "-" + *route.Name)
- } else {
- log.Println("Service name or route name is empty. This is not recommended." +
- "Please, provide a name for the service and the route before generating Kong Ingress Controller manifests.")
- continue
+// Helper function to add annotations from a route to an ingress
+func addAnnotationsFromRoute(route *file.FRoute, annotations map[string]string) {
+ if route.Protocols != nil {
+ var protocols []string
+ for _, protocol := range route.Protocols {
+ if protocol != nil {
+ protocols = append(protocols, *protocol)
}
- ingressClassName := ClassName
- k8sIngress.Spec.IngressClassName = &ingressClassName
- k8sIngress.ObjectMeta.Annotations = make(map[string]string)
-
- // add konghq.com/protocols annotation if route.Protocols is not nil
- if route.Protocols != nil {
- var protocols string
- for _, protocol := range route.Protocols {
- if protocols == "" {
- protocols = *protocol
- } else {
- protocols = protocols + "," + *protocol
- }
- }
- k8sIngress.ObjectMeta.Annotations["konghq.com/protocols"] = protocols
- }
-
- // add konghq.com/strip-path annotation if route.StripPath is not nil
- if route.StripPath != nil {
- k8sIngress.ObjectMeta.Annotations["konghq.com/strip-path"] = strconv.FormatBool(*route.StripPath)
- }
-
- // add konghq.com/preserve-host annotation if route.PreserveHost is not nil
- if route.PreserveHost != nil {
- k8sIngress.ObjectMeta.Annotations["konghq.com/preserve-host"] = strconv.FormatBool(*route.PreserveHost)
- }
-
- // add konghq.com/regex-priority annotation if route.RegexPriority is not nil
- if route.RegexPriority != nil {
- k8sIngress.ObjectMeta.Annotations["konghq.com/regex-priority"] = strconv.Itoa(*route.RegexPriority)
+ }
+ annotations["konghq.com/protocols"] = strings.Join(protocols, ",")
+ }
+ if route.StripPath != nil {
+ annotations["konghq.com/strip-path"] = strconv.FormatBool(*route.StripPath)
+ }
+ if route.PreserveHost != nil {
+ annotations["konghq.com/preserve-host"] = strconv.FormatBool(*route.PreserveHost)
+ }
+ if route.RegexPriority != nil {
+ annotations["konghq.com/regex-priority"] = strconv.Itoa(*route.RegexPriority)
+ }
+ if route.HTTPSRedirectStatusCode != nil {
+ annotations["konghq.com/https-redirect-status-code"] = strconv.Itoa(*route.HTTPSRedirectStatusCode)
+ }
+ if route.Headers != nil {
+ for key, value := range route.Headers {
+ annotations["konghq.com/headers."+key] = strings.Join(value, ",")
+ }
+ }
+ if route.PathHandling != nil {
+ annotations["konghq.com/path-handling"] = *route.PathHandling
+ }
+ if route.SNIs != nil {
+ var snis []string
+ for _, sni := range route.SNIs {
+ if sni != nil {
+ snis = append(snis, *sni)
}
-
- // add konghq.com/https-redirect-status-code annotation if route.HTTPSRedirectStatusCode is not nil
- if route.HTTPSRedirectStatusCode != nil {
- value := strconv.Itoa(*route.HTTPSRedirectStatusCode)
- k8sIngress.ObjectMeta.Annotations["konghq.com/https-redirect-status-code"] = value
+ }
+ annotations["konghq.com/snis"] = strings.Join(snis, ",")
+ }
+ if route.RequestBuffering != nil {
+ annotations["konghq.com/request-buffering"] = strconv.FormatBool(*route.RequestBuffering)
+ }
+ if route.ResponseBuffering != nil {
+ annotations["konghq.com/response-buffering"] = strconv.FormatBool(*route.ResponseBuffering)
+ }
+ if route.Methods != nil {
+ var methods []string
+ for _, method := range route.Methods {
+ if method != nil {
+ methods = append(methods, *method)
}
-
- // add konghq.com/headers.* annotation if route.Headers is not nil
- if route.Headers != nil {
- for key, value := range route.Headers {
- k8sIngress.ObjectMeta.Annotations["konghq.com/headers."+key] = strings.Join(value, ",")
- }
+ }
+ annotations["konghq.com/methods"] = strings.Join(methods, ",")
+ }
+ if route.Tags != nil {
+ var tags []string
+ for _, tag := range route.Tags {
+ if tag != nil {
+ tags = append(tags, *tag)
}
+ }
+ annotations["konghq.com/tags"] = strings.Join(tags, ",")
+ }
+}
- // add konghq.com/path-handling annotation if route.PathHandling is not nil
- if route.PathHandling != nil {
- k8sIngress.ObjectMeta.Annotations["konghq.com/path-handling"] = *route.PathHandling
+// Helper function to create ingress paths
+func createIngressPaths(
+ route *file.FRoute,
+ serviceName string,
+ servicePort *int,
+ pathType k8snetv1.PathType,
+) []k8snetv1.HTTPIngressPath {
+ var paths []k8snetv1.HTTPIngressPath
+ for _, path := range route.Paths {
+ sCopy := *path
+ if strings.HasPrefix(sCopy, "~") {
+ sCopy = "/" + sCopy
+ }
+ backend := k8snetv1.IngressBackend{
+ Service: &k8snetv1.IngressServiceBackend{
+ Name: serviceName,
+ },
+ }
+ if servicePort != nil {
+ // check that the port is within the valid range
+ if *servicePort > 65535 || *servicePort < 0 {
+ log.Fatalf("Port %d is not within the valid range. Please provide a port between 0 and 65535.\n", *servicePort)
}
+ //nolint: gosec
+ backend.Service.Port.Number = int32(*servicePort)
+ }
+ paths = append(paths, k8snetv1.HTTPIngressPath{
+ Path: sCopy,
+ PathType: &pathType,
+ Backend: backend,
+ })
+ }
+ return paths
+}
- // add konghq.com/snis annotation if route.SNIs is not nil
- if route.SNIs != nil {
- var snis string
- for _, sni := range route.SNIs {
- if snis == "" {
- snis = *sni
- } else {
- snis = snis + "," + *sni
- }
- }
- k8sIngress.ObjectMeta.Annotations["konghq.com/snis"] = snis
+// Convert route to Ingress (Ingress API)
+func populateKICIngressesWithAnnotations(content *file.Content, kicContent *KICContent) error {
+ for _, service := range content.Services {
+ if service.Name == nil {
+ log.Println("Service name is empty. Please provide a name for the service.")
+ continue
+ }
+ serviceName := *service.Name
+ for _, route := range service.Routes {
+ if route.Name == nil {
+ log.Println("Route name is empty. Please provide a name for the route.")
+ continue
}
+ routeName := *route.Name
- // add konghq.com/request-buffering annotation if route.RequestBuffering is not nil
- if route.RequestBuffering != nil {
- k8sIngress.ObjectMeta.Annotations["konghq.com/request-buffering"] = strconv.FormatBool(*route.RequestBuffering)
+ k8sIngress := k8snetv1.Ingress{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "networking.k8s.io/v1",
+ Kind: "Ingress",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(serviceName + "-" + routeName),
+ Annotations: make(map[string]string),
+ },
}
+ ingressClassName := ClassName
+ k8sIngress.Spec.IngressClassName = &ingressClassName
- // add konghq.com/response-buffering annotation if route.ResponseBuffering is not nil
- if route.ResponseBuffering != nil {
- k8sIngress.ObjectMeta.Annotations["konghq.com/response-buffering"] = strconv.FormatBool(*route.ResponseBuffering)
- }
+ addAnnotationsFromRoute(route, k8sIngress.ObjectMeta.Annotations)
- // add konghq.com/methods annotation if route.Methods is not nil
- if route.Methods != nil {
- var methods string
- for _, method := range route.Methods {
- if methods == "" {
- methods = *method
- } else {
- methods = methods + "," + *method
- }
- }
- k8sIngress.ObjectMeta.Annotations["konghq.com/methods"] = methods
- }
+ pathType := k8snetv1.PathTypeImplementationSpecific
if len(route.Hosts) == 0 {
- // iterate route.Paths and create a k8sIngress.Spec.Rules for each one.
- // If service.Port is not nil, add it to the k8sIngress.Spec.Rules
ingressRule := k8snetv1.IngressRule{
IngressRuleValue: k8snetv1.IngressRuleValue{
HTTP: &k8snetv1.HTTPIngressRuleValue{
- Paths: []k8snetv1.HTTPIngressPath{},
+ Paths: createIngressPaths(route, serviceName, service.Port, pathType),
},
},
}
- for _, path := range route.Paths {
- // if path starts with ~ then add / to the beginning of the path
- // see: https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/upgrade-kong-3x/#update-ingr
- // ess-regular-expression-paths-for-kong-3x-compatibility
- sCopy := *path
- if strings.HasPrefix(*path, "~") {
- sCopy = "/" + *path
- }
- if service.Port != nil {
- ingressRule.IngressRuleValue.HTTP.Paths = append(ingressRule.IngressRuleValue.HTTP.Paths,
- k8snetv1.HTTPIngressPath{
- Path: sCopy,
- PathType: &pathTypeImplSpecific,
- Backend: k8snetv1.IngressBackend{
- Service: &k8snetv1.IngressServiceBackend{
- Name: *service.Name,
- Port: k8snetv1.ServiceBackendPort{
- Number: int32(*service.Port), //nolint:gosec
- },
- },
- },
- })
- } else {
- ingressRule.IngressRuleValue.HTTP.Paths = append(ingressRule.IngressRuleValue.HTTP.Paths,
- k8snetv1.HTTPIngressPath{
- Path: sCopy,
- PathType: &pathTypeImplSpecific,
- Backend: k8snetv1.IngressBackend{
- Service: &k8snetv1.IngressServiceBackend{
- Name: *service.Name,
- },
- },
- })
- }
- }
k8sIngress.Spec.Rules = append(k8sIngress.Spec.Rules, ingressRule)
} else {
- // Iterate route.Hosts and create a k8sIngress.Spec.Rules for each one.
- // For each host, iterate route.Paths and add a k8snetv1.HTTPIngressPath to the k8sIngress.Spec.Rules.
- // If service.Port is not nil, add it to the k8sIngress.Spec.Rules
for _, host := range route.Hosts {
ingressRule := k8snetv1.IngressRule{
Host: *host,
IngressRuleValue: k8snetv1.IngressRuleValue{
HTTP: &k8snetv1.HTTPIngressRuleValue{
- Paths: []k8snetv1.HTTPIngressPath{},
+ Paths: createIngressPaths(route, serviceName, service.Port, pathType),
},
},
}
- for _, path := range route.Paths {
- // if path starts with ~ then add / to the beginning of the path
- // see: https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/upgrade-kong-3x/#update-ingr
- // ess-regular-expression-paths-for-kong-3x-compatibility
- sCopy := *path
- if strings.HasPrefix(*path, "~") {
- sCopy = "/" + *path
- }
- if service.Port != nil {
- ingressRule.IngressRuleValue.HTTP.Paths = append(ingressRule.IngressRuleValue.HTTP.Paths,
- k8snetv1.HTTPIngressPath{
- Path: sCopy,
- PathType: &pathTypeImplSpecific,
- Backend: k8snetv1.IngressBackend{
- Service: &k8snetv1.IngressServiceBackend{
- Name: *service.Name,
- Port: k8snetv1.ServiceBackendPort{
- Number: int32(*service.Port), //nolint:gosec
- },
- },
- },
- })
- } else {
- ingressRule.IngressRuleValue.HTTP.Paths = append(ingressRule.IngressRuleValue.HTTP.Paths,
- k8snetv1.HTTPIngressPath{
- Path: sCopy,
- PathType: &pathTypeImplSpecific,
- Backend: k8snetv1.IngressBackend{
- Service: &k8snetv1.IngressServiceBackend{
- Name: *service.Name,
- },
- },
- })
- }
- }
k8sIngress.Spec.Rules = append(k8sIngress.Spec.Rules, ingressRule)
}
}
- err := addPluginsToRoute(service, route, k8sIngress, kicContent)
+ err := addPluginsToRoute(service, route, &k8sIngress, kicContent)
if err != nil {
return err
}
@@ -235,319 +180,77 @@ func populateKICIngressesWithAnnotations(content *file.Content, kicContent *KICC
return nil
}
+// Simplify the plugin addition function
func addPluginsToRoute(
service file.FService,
route *file.FRoute,
- ingress k8snetv1.Ingress,
+ ingress *k8snetv1.Ingress,
kicContent *KICContent,
) error {
for _, plugin := range route.Plugins {
- var kongPlugin kicv1.KongPlugin
- kongPlugin.APIVersion = KICAPIVersion
- kongPlugin.Kind = KongPluginKind
- if plugin.Name != nil && route.Name != nil && service.Name != nil {
- kongPlugin.ObjectMeta.Name = calculateSlug(*service.Name + "-" + *route.Name + "-" + *plugin.Name)
- } else {
- log.Println("Service name, route name or plugin name is empty. This is not recommended." +
- "Please, provide a name for the service, route and the plugin before generating Kong Ingress Controller manifests.")
+ if plugin.Name == nil {
+ log.Println("Plugin name is empty. Please provide a name for the plugin.")
continue
}
- kongPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- kongPlugin.PluginName = *plugin.Name
-
- var configJSON apiextensionsv1.JSON
- var err error
- configJSON.Raw, err = json.Marshal(plugin.Config)
- if err != nil {
- return err
+ pluginName := *plugin.Name
+ kongPlugin := kicv1.KongPlugin{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: KICAPIVersion,
+ Kind: KongPluginKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(*service.Name + "-" + *route.Name + "-" + pluginName),
+ Annotations: map[string]string{IngressClass: ClassName},
+ },
+ PluginName: pluginName,
}
- kongPlugin.Config = configJSON
- if ingress.ObjectMeta.Annotations["konghq.com/plugins"] == "" {
- ingress.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.ObjectMeta.Name
- } else {
- annotations := ingress.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.ObjectMeta.Name
- ingress.ObjectMeta.Annotations["konghq.com/plugins"] = annotations
+ // Populate plugin fields
+ if plugin.Enabled != nil {
+ kongPlugin.Disabled = !*plugin.Enabled
}
-
- kicContent.KongPlugins = append(kicContent.KongPlugins, kongPlugin)
- }
- return nil
-}
-
-// HeadersByNameTypeAndValue is a type to sort headers by name, type and value.
-// This is needed to ensure that the order of headers is consistent across runs.
-type HeadersByNameTypeAndValue []k8sgwapiv1.HTTPHeaderMatch
-
-func (a HeadersByNameTypeAndValue) Len() int { return len(a) }
-func (a HeadersByNameTypeAndValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a HeadersByNameTypeAndValue) Less(i, j int) bool {
- if a[i].Name < a[j].Name {
- return true
- }
- if a[i].Name > a[j].Name {
- return false
- }
-
- if a[i].Type != nil && a[j].Type == nil {
- return true
- }
- if a[i].Type == nil && a[j].Type != nil {
- return false
- }
-
- if *a[i].Type < *a[j].Type {
- return true
- }
- if *a[i].Type > *a[j].Type {
- return false
- }
- return a[i].Value < a[j].Value
-}
-
-// Convert route to HTTPRoute (Gateway API)
-func populateKICIngressesWithGatewayAPI(content *file.Content, kicContent *KICContent) error {
- for _, service := range content.Services {
- for _, route := range service.Routes {
- var httpRoute k8sgwapiv1.HTTPRoute
- httpRoute.Kind = "HTTPRoute"
- if targetKICVersionAPI == KICV3GATEWAY {
- httpRoute.APIVersion = GatewayAPIVersionV1
- } else {
- httpRoute.APIVersion = GatewayAPIVersionV1Beta1
- }
- if service.Name != nil && route.Name != nil {
- httpRoute.ObjectMeta.Name = calculateSlug(*service.Name + "-" + *route.Name)
- } else {
- log.Println("Service name or route name is empty. This is not recommended." +
- "Please, provide a name for the service and the route before generating HTTPRoute manifests.")
- continue
- }
- httpRoute.ObjectMeta.Annotations = make(map[string]string)
-
- // add konghq.com/preserve-host annotation if route.PreserveHost is not nil
- if route.PreserveHost != nil {
- httpRoute.ObjectMeta.Annotations["konghq.com/preserve-host"] = strconv.FormatBool(*route.PreserveHost)
- }
-
- // add konghq.com/strip-path annotation if route.StripPath is not nil
- if route.StripPath != nil {
- httpRoute.ObjectMeta.Annotations["konghq.com/strip-path"] = strconv.FormatBool(*route.StripPath)
- }
-
- // add konghq.com/https-redirect-status-code annotation if route.HTTPSRedirectStatusCode is not nil
- if route.HTTPSRedirectStatusCode != nil {
- value := strconv.Itoa(*route.HTTPSRedirectStatusCode)
- httpRoute.ObjectMeta.Annotations["konghq.com/https-redirect-status-code"] = value
- }
-
- // add konghq.com/regex-priority annotation if route.RegexPriority is not nil
- if route.RegexPriority != nil {
- httpRoute.ObjectMeta.Annotations["konghq.com/regex-priority"] = strconv.Itoa(*route.RegexPriority)
- }
-
- // add konghq.com/path-handling annotation if route.PathHandling is not nil
- if route.PathHandling != nil {
- httpRoute.ObjectMeta.Annotations["konghq.com/path-handling"] = *route.PathHandling
- }
-
- // add konghq.com/snis annotation if route.SNIs is not nil
- if route.SNIs != nil {
- var snis string
- for _, sni := range route.SNIs {
- if snis == "" {
- snis = *sni
- } else {
- snis = snis + "," + *sni
- }
- }
- httpRoute.ObjectMeta.Annotations["konghq.com/snis"] = snis
- }
-
- // add konghq.com/request-buffering annotation if route.RequestBuffering is not nil
- if route.RequestBuffering != nil {
- httpRoute.ObjectMeta.Annotations["konghq.com/request-buffering"] = strconv.FormatBool(*route.RequestBuffering)
- }
-
- // add konghq.com/response-buffering annotation if route.ResponseBuffering is not nil
- if route.ResponseBuffering != nil {
- httpRoute.ObjectMeta.Annotations["konghq.com/response-buffering"] = strconv.FormatBool(*route.ResponseBuffering)
- }
-
- // if route.hosts is not nil, add them to the httpRoute
- if route.Hosts != nil {
- for _, host := range route.Hosts {
- httpRoute.Spec.Hostnames = append(httpRoute.Spec.Hostnames, k8sgwapiv1.Hostname(*host))
- }
- }
-
- // add kong as the spec.parentRef.name
- httpRoute.Spec.ParentRefs = append(httpRoute.Spec.ParentRefs, k8sgwapiv1.ParentReference{
- Name: k8sgwapiv1.ObjectName(ClassName),
- })
-
- // add service details to HTTPBackendRef
-
- backendRef := k8sgwapiv1.BackendRef{
- BackendObjectReference: k8sgwapiv1.BackendObjectReference{
- Name: k8sgwapiv1.ObjectName(*service.Name),
- },
- }
- if service.Port != nil {
- portNumber := k8sgwapiv1.PortNumber(*service.Port) //nolint:gosec
- backendRef.Port = &portNumber
+ if plugin.RunOn != nil {
+ kongPlugin.RunOn = *plugin.RunOn
+ }
+ if plugin.Ordering != nil {
+ kongPlugin.Ordering = &kong.PluginOrdering{
+ Before: plugin.Ordering.Before,
+ After: plugin.Ordering.After,
}
-
- var httpHeaderMatch []k8sgwapiv1.HTTPHeaderMatch
- headerMatchExact := k8sgwapiv1.HeaderMatchExact
- headerMatchRegex := k8sgwapiv1.HeaderMatchRegularExpression
- // if route.Headers is not nil, add them to the httpHeaderMatch
- if route.Headers != nil {
- for key, values := range route.Headers {
- // if values has only one value and that value starts with
- // the special prefix ~*, the value is interpreted as a regular expression.
- if len(values) == 1 && strings.HasPrefix(values[0], "~*") {
- httpHeaderMatch = append(httpHeaderMatch, k8sgwapiv1.HTTPHeaderMatch{
- Name: k8sgwapiv1.HTTPHeaderName(key),
- Value: values[0][2:],
- Type: &headerMatchRegex,
- })
- } else {
- // if multiple values are present, add them as comma separated values
- // if only one value is present, add it as a single value
- var value string
- if len(values) > 1 {
- value = strings.Join(values, ",")
- } else {
- value = values[0]
- }
- httpHeaderMatch = append(httpHeaderMatch, k8sgwapiv1.HTTPHeaderMatch{
- Name: k8sgwapiv1.HTTPHeaderName(key),
- Value: value,
- Type: &headerMatchExact,
- })
- }
+ }
+ if plugin.Protocols != nil {
+ var protocols []string
+ for _, protocol := range plugin.Protocols {
+ if protocol != nil {
+ protocols = append(protocols, *protocol)
}
- sort.Sort(HeadersByNameTypeAndValue(httpHeaderMatch))
}
-
- // If path is not nil, then for each path, for each method, add a httpRouteRule
- // to the httpRoute
- if route.Paths != nil {
- for _, path := range route.Paths {
- var httpPathMatch k8sgwapiv1.HTTPPathMatch
- pathMatchRegex := k8sgwapiv1.PathMatchRegularExpression
- pathMatchPrefix := k8sgwapiv1.PathMatchPathPrefix
-
- if strings.HasPrefix(*path, "~") {
- httpPathMatch.Type = &pathMatchRegex
- regexPath := (*path)[1:]
- httpPathMatch.Value = ®exPath
- } else {
- httpPathMatch.Type = &pathMatchPrefix
- httpPathMatch.Value = path
- }
-
- // if no method is specified, add a httpRouteRule to the httpRoute with headers and path
- if route.Methods == nil {
- httpRoute.Spec.Rules = append(httpRoute.Spec.Rules, k8sgwapiv1.HTTPRouteRule{
- Matches: []k8sgwapiv1.HTTPRouteMatch{
- {
- Path: &httpPathMatch,
- Headers: httpHeaderMatch,
- },
- },
- BackendRefs: []k8sgwapiv1.HTTPBackendRef{
- {
- BackendRef: backendRef,
- },
- },
- })
- }
-
- for _, method := range route.Methods {
- httpMethod := k8sgwapiv1.HTTPMethod(*method)
- httpRoute.Spec.Rules = append(httpRoute.Spec.Rules, k8sgwapiv1.HTTPRouteRule{
- Matches: []k8sgwapiv1.HTTPRouteMatch{
- {
- Path: &httpPathMatch,
- Method: &httpMethod,
- Headers: httpHeaderMatch,
- },
- },
- BackendRefs: []k8sgwapiv1.HTTPBackendRef{
- {
- BackendRef: backendRef,
- },
- },
- })
- }
- }
- } else {
- // If path is nil, then for each method, add a httpRouteRule
- // to the httpRoute with headers and no path
- for _, method := range route.Methods {
- httpMethod := k8sgwapiv1.HTTPMethod(*method)
- httpRoute.Spec.Rules = append(httpRoute.Spec.Rules, k8sgwapiv1.HTTPRouteRule{
- Matches: []k8sgwapiv1.HTTPRouteMatch{
- {
- Method: &httpMethod,
- Headers: httpHeaderMatch,
- },
- },
- BackendRefs: []k8sgwapiv1.HTTPBackendRef{
- {
- BackendRef: backendRef,
- },
- },
- })
+ kongPlugin.Protocols = kicv1.StringsToKongProtocols(protocols)
+ }
+ if plugin.Tags != nil {
+ var tags []string
+ for _, tag := range plugin.Tags {
+ if tag != nil {
+ tags = append(tags, *tag)
}
}
- err := addPluginsToGatewayAPIRoute(service, route, httpRoute, kicContent)
- if err != nil {
- return err
- }
- kicContent.HTTPRoutes = append(kicContent.HTTPRoutes, httpRoute)
- }
- }
- return nil
-}
-
-func addPluginsToGatewayAPIRoute(
- service file.FService, route *file.FRoute, httpRoute k8sgwapiv1.HTTPRoute, kicContent *KICContent,
-) error {
- for _, plugin := range route.Plugins {
- var kongPlugin kicv1.KongPlugin
- kongPlugin.APIVersion = KICAPIVersion
- kongPlugin.Kind = KongPluginKind
- if plugin.Name != nil && route.Name != nil && service.Name != nil {
- kongPlugin.ObjectMeta.Name = calculateSlug(*service.Name + "-" + *route.Name + "-" + *plugin.Name)
- } else {
- log.Println("Service name, route name or plugin name is empty. This is not recommended." +
- "Please, provide a name for the service, route and the plugin before generating Kong Ingress Controller manifests.")
- continue
+ kongPlugin.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
}
- kongPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- kongPlugin.PluginName = *plugin.Name
- var configJSON apiextensionsv1.JSON
- var err error
- configJSON.Raw, err = json.Marshal(plugin.Config)
+ configJSON, err := json.Marshal(plugin.Config)
if err != nil {
return err
}
- kongPlugin.Config = configJSON
+ kongPlugin.Config = apiextensionsv1.JSON{
+ Raw: configJSON,
+ }
- // add plugins as extensionRef under filters for every rule
- for i := range httpRoute.Spec.Rules {
- httpRoute.Spec.Rules[i].Filters = append(httpRoute.Spec.Rules[i].Filters, k8sgwapiv1.HTTPRouteFilter{
- ExtensionRef: &k8sgwapiv1.LocalObjectReference{
- Name: k8sgwapiv1.ObjectName(kongPlugin.ObjectMeta.Name),
- Kind: KongPluginKind,
- Group: "configuration.konghq.com",
- },
- Type: k8sgwapiv1.HTTPRouteFilterExtensionRef,
- })
+ // Add plugin reference to ingress annotations
+ pluginsAnnotation := ingress.ObjectMeta.Annotations["konghq.com/plugins"]
+ if pluginsAnnotation == "" {
+ ingress.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.ObjectMeta.Name
+ } else {
+ ingress.ObjectMeta.Annotations["konghq.com/plugins"] = pluginsAnnotation + "," + kongPlugin.ObjectMeta.Name
}
kicContent.KongPlugins = append(kicContent.KongPlugins, kongPlugin)
diff --git a/kong2kic/service.go b/kong2kic/service.go
index 7ce9a06e0..756b03bb3 100644
--- a/kong2kic/service.go
+++ b/kong2kic/service.go
@@ -1,147 +1,159 @@
package kong2kic
import (
- "encoding/json"
"log"
"strconv"
"strings"
"github.com/kong/go-database-reconciler/pkg/file"
- kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
k8scorev1 "k8s.io/api/core/v1"
- apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
+// Main function to populate KIC services with annotations
func populateKICServicesWithAnnotations(content *file.Content, kicContent *KICContent) error {
- // Iterate Kong Services and create k8s Services,
- // then create KongIngress resources for Kong Service Upstream data.
- // Finally, create KongPlugin resources for each plugin
- // associated with the service.
- for i := range content.Services {
- service := content.Services[i]
-
- var k8sService k8scorev1.Service
- var protocol k8scorev1.Protocol
-
- k8sService.TypeMeta.APIVersion = "v1"
- k8sService.TypeMeta.Kind = "Service"
- if service.Name != nil {
- k8sService.ObjectMeta.Name = calculateSlug(*service.Name)
- } else {
- log.Println("Service name is empty. This is not recommended." +
- "Please, provide a name for the service before generating Kong Ingress Controller manifests.")
+ for _, service := range content.Services {
+ if service.Name == nil {
+ log.Println("Service name is empty. Please provide a name for the service.")
continue
}
- k8sService.ObjectMeta.Annotations = make(map[string]string)
- // default TCP unless service.Protocol is equal to k8scorev1.ProtocolUDP
- if service.Protocol != nil && k8scorev1.Protocol(strings.ToUpper(*service.Protocol)) == k8scorev1.ProtocolUDP {
- protocol = k8scorev1.ProtocolUDP
- } else {
- protocol = k8scorev1.ProtocolTCP
- }
+ // Create Kubernetes service
+ k8sService := createK8sService(&service, content.Upstreams)
- if service.Port != nil {
- sPort := k8scorev1.ServicePort{
- Protocol: protocol,
- Port: int32(*service.Port), //nolint:gosec
- TargetPort: intstr.IntOrString{
- IntVal: int32(*service.Port), //nolint:gosec
- },
- }
- k8sService.Spec.Ports = append(k8sService.Spec.Ports, sPort)
- }
+ // Add annotations from the service object
+ addAnnotationsFromService(&service, k8sService.ObjectMeta.Annotations)
- if service.Name != nil {
- k8sService.Spec.Selector = map[string]string{"app": *service.Name}
+ // Populate upstream policies based on KIC version
+ if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
+ populateKICUpstreamPolicy(content, &service, k8sService, kicContent)
} else {
- log.Println("Service without a name is not recommended")
+ populateKICUpstream(content, &service, k8sService, kicContent)
}
- // add konghq.com/read-timeout annotation if service.ReadTimeout is not nil
- if service.ReadTimeout != nil {
- k8sService.ObjectMeta.Annotations["konghq.com/read-timeout"] = strconv.Itoa(*service.ReadTimeout)
+ // Add plugins to the service
+ err := addPluginsToService(&service, k8sService, kicContent)
+ if err != nil {
+ return err
}
- // add konghq.com/write-timeout annotation if service.WriteTimeout is not nil
- if service.WriteTimeout != nil {
- k8sService.ObjectMeta.Annotations["konghq.com/write-timeout"] = strconv.Itoa(*service.WriteTimeout)
- }
+ // Append the Kubernetes service to KIC content
+ kicContent.Services = append(kicContent.Services, *k8sService)
+ }
+ return nil
+}
- // add konghq.com/connect-timeout annotation if service.ConnectTimeout is not nil
- if service.ConnectTimeout != nil {
- k8sService.ObjectMeta.Annotations["konghq.com/connect-timeout"] = strconv.Itoa(*service.ConnectTimeout)
- }
+// Helper function to create a Kubernetes Service from a Kong service
+func createK8sService(service *file.FService, upstreams []file.FUpstream) *k8scorev1.Service {
+ k8sService := &k8scorev1.Service{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "v1",
+ Kind: "Service",
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(*service.Name),
+ Annotations: make(map[string]string),
+ },
+ }
- // add konghq.com/protocol annotation if service.Protocol is not nil
- if service.Protocol != nil {
- k8sService.ObjectMeta.Annotations["konghq.com/protocol"] = *service.Protocol
- }
+ // Determine the protocol (default to TCP)
+ protocol := k8scorev1.ProtocolTCP
+ if service.Protocol != nil && strings.ToUpper(*service.Protocol) == string(k8scorev1.ProtocolUDP) {
+ protocol = k8scorev1.ProtocolUDP
+ }
- // add konghq.com/path annotation if service.Path is not nil
- if service.Path != nil {
- k8sService.ObjectMeta.Annotations["konghq.com/path"] = *service.Path
+ // Set the service port
+ if service.Port != nil {
+ // check that the port is within the valid range
+ if *service.Port > 65535 || *service.Port < 0 {
+ log.Fatalf("Port %d is not within the valid range. Please provide a port between 0 and 65535.\n", *service.Port)
}
-
- // add konghq.com/retries annotation if service.Retries is not nil
- if service.Retries != nil {
- k8sService.ObjectMeta.Annotations["konghq.com/retries"] = strconv.Itoa(*service.Retries)
+ servicePort := k8scorev1.ServicePort{
+ Protocol: protocol,
+ //nolint: gosec
+ Port: int32(*service.Port),
+ TargetPort: intstr.FromInt(*service.Port),
}
+ k8sService.Spec.Ports = []k8scorev1.ServicePort{servicePort}
+ }
- if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
- // Use KongUpstreamPolicy for KICv3
- populateKICUpstreamPolicy(content, &service, &k8sService, kicContent)
- } else {
- // Use KongIngress for KICv2
- populateKICUpstream(content, &service, &k8sService, kicContent)
- }
+ // Configure the service selector or external name
+ if service.Host == nil {
+ k8sService.Spec.Selector = map[string]string{"app": *service.Name}
+ } else {
+ k8sService.Spec.Type = k8scorev1.ServiceTypeExternalName
+ k8sService.Spec.ExternalName = *service.Host
- // iterate over the plugins for this service, create a KongPlugin for each one and add an annotation to the service
- // transform the plugin config from map[string]interface{} to apiextensionsv1.JSON
- // create a plugins annotation in the k8sservice to link the plugin to it
- err := addPluginsToService(service, k8sService, kicContent)
- if err != nil {
- return err
+ // Check if the host matches any upstream
+ if isUpstreamReferenced(service.Host, upstreams) {
+ k8sService.Spec.Selector = map[string]string{"app": *service.Name}
+ k8sService.Spec.Type = ""
+ k8sService.Spec.ExternalName = ""
}
+ }
- kicContent.Services = append(kicContent.Services, k8sService)
+ return k8sService
+}
+// Helper function to check if the service host matches any upstream name
+func isUpstreamReferenced(host *string, upstreams []file.FUpstream) bool {
+ for _, upstream := range upstreams {
+ if upstream.Name != nil && strings.EqualFold(*upstream.Name, *host) {
+ return true
+ }
}
- return nil
+ return false
}
-func addPluginsToService(service file.FService, k8sService k8scorev1.Service, kicContent *KICContent) error {
+// Helper function to add annotations from a service to a Kubernetes service
+func addAnnotationsFromService(service *file.FService, annotations map[string]string) {
+ if service.Protocol != nil {
+ annotations["konghq.com/protocol"] = *service.Protocol
+ }
+ if service.Path != nil {
+ annotations["konghq.com/path"] = *service.Path
+ }
+ if service.ClientCertificate != nil && service.ClientCertificate.ID != nil {
+ annotations["konghq.com/client-cert"] = *service.ClientCertificate.ID
+ }
+ if service.ReadTimeout != nil {
+ annotations["konghq.com/read-timeout"] = strconv.Itoa(*service.ReadTimeout)
+ }
+ if service.WriteTimeout != nil {
+ annotations["konghq.com/write-timeout"] = strconv.Itoa(*service.WriteTimeout)
+ }
+ if service.ConnectTimeout != nil {
+ annotations["konghq.com/connect-timeout"] = strconv.Itoa(*service.ConnectTimeout)
+ }
+ if service.Retries != nil {
+ annotations["konghq.com/retries"] = strconv.Itoa(*service.Retries)
+ }
+ addTagsToAnnotations(service.Tags, annotations)
+}
+
+// Helper function to add plugins to a service
+func addPluginsToService(service *file.FService, k8sService *k8scorev1.Service, kicContent *KICContent) error {
for _, plugin := range service.Plugins {
- var kongPlugin kicv1.KongPlugin
- kongPlugin.APIVersion = KICAPIVersion
- kongPlugin.Kind = KongPluginKind
- if plugin.Name != nil && service.Name != nil {
- kongPlugin.ObjectMeta.Name = calculateSlug(*service.Name + "-" + *plugin.Name)
- } else {
- log.Println("Service name or plugin name is empty. This is not recommended." +
- "Please, provide a name for the service and the plugin before generating Kong Ingress Controller manifests.")
+ if plugin.Name == nil || service.Name == nil {
+ log.Println("Service name or plugin name is empty. Please provide names for both.")
continue
}
- kongPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
- kongPlugin.PluginName = *plugin.Name
- var configJSON apiextensionsv1.JSON
- var err error
- configJSON.Raw, err = json.Marshal(plugin.Config)
+ // Create a KongPlugin
+ kongPlugin, err := createKongPlugin(plugin, *service.Name)
if err != nil {
return err
}
- kongPlugin.Config = configJSON
-
- if k8sService.ObjectMeta.Annotations["konghq.com/plugins"] == "" {
- k8sService.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.ObjectMeta.Name
- } else {
- annotations := k8sService.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.ObjectMeta.Name
- k8sService.ObjectMeta.Annotations["konghq.com/plugins"] = annotations
+ if kongPlugin == nil {
+ continue
}
- kicContent.KongPlugins = append(kicContent.KongPlugins, kongPlugin)
+ // Add the plugin name to the service annotations
+ addPluginToAnnotations(kongPlugin.ObjectMeta.Name, k8sService.ObjectMeta.Annotations)
+
+ // Append the KongPlugin to KIC content
+ kicContent.KongPlugins = append(kicContent.KongPlugins, *kongPlugin)
}
return nil
}
diff --git a/kong2kic/testdata/README.md b/kong2kic/testdata/README.md
new file mode 100644
index 000000000..f187b1662
--- /dev/null
+++ b/kong2kic/testdata/README.md
@@ -0,0 +1,64 @@
+
+# Service
+- A Kong Service maps to a Kubernetes Service.
+- The generated k8s service is independent of KIC version or GW/INGRESS API.
+- For each Kong service, it creates a new Kubernetes service.
+- If the service has a name, it is converted into a slug format using the calculateSlug function and assigned to the Kubernetes service's name.
+- If the service doesn't have a name, a warning message is logged and it is skipped.
+- The protocol defaults to TCP unless the service's protocol is explicitly set to UDP.
+- If the service has a specified port, a ServicePort object is created with the protocol and port information, and this object is appended to the Kubernetes service's ports.
+- The service name, is used as a selector for the Kubernetes service.
+- Various properties of the service (like ReadTimeout, WriteTimeout, ConnectTimeout, Protocol, Path, and Retries) are added as annotations to the Kubernetes service.
+- If the service host is informed then search for an Upstream which name matches. If there is no upstream, then configure an external service.
+
+# Route
+- A Kong Route maps to a HTTPRoute (Gateway API) or Ingress (Ingress API)
+
+## Ingress API
+- The generated k8s Ingress is independent of KIC version.
+- If the service and route names are not nil, they are used to generate a slug that is used as the name of the Ingress resource. If either the service or route name is nil, a log message is printed and the loop continues to the next iteration.
+- It then checks various properties of the route (like Protocols, StripPath, PreserveHost, etc.) and if they are not nil, it adds corresponding annotations to the k8sIngress.
+- If the route doesn't have hosts defined, it creates an IngressRule for each path in the route.
+- If the service has a port, it is included in the IngressRule.
+- If the route does have hosts, it creates an IngressRule for each host and for each path in the route. Again, if the service has a port,
+it is included in the IngressRule.
+
+## Gateway API
+- The generated k8s HTTPRoute is slighlty different for KIC v2 vs v3. The only difference is `apiVersion: gateway.networking.k8s.io/v1beta1` vs `apiVersion: gateway.networking.k8s.io/v1`.
+- If the service and route names are not nil, they are used to generate a slug that is used as the name of the Ingress resource. If either the service or route name is nil, a log message is printed and the loop continues to the next iteration.
+- It then checks various properties of the route (like Protocols, StripPath, PreserveHost, etc.) and if they are not nil, it adds corresponding annotations.
+- It then checks if route.Hosts is not nil and if it's not, it appends each host to httpRoute.Spec.Hostnames. It also appends a ParentReference with the name "kong" to httpRoute.Spec.ParentRefs.
+- It then creates a BackendRef with the service name and port and assigns it to backendRef. It also creates an HTTPHeaderMatch slice and populates it with header matches if route.Headers is not nil.
+- Next, the function checks if route.Paths is not nil and if it's not, it creates an HTTPRouteRule for each path and each method in the route and
+appends it to httpRoute.Spec.Rules. If route.Paths is nil, it creates an HTTPRouteRule for each method in the route with no path and appends it to httpRoute.Spec.Rules
+
+# Plugin
+## Service and Route plugins
+- A Kong Plugin maps to a KongPlugin in K8s.
+- Plugins do not depend on KIC v2 vs v3.
+- The plugin configuration is copied verbatim and an annotation is added to the entity to which the plugin is applied (Service, Ingress, Consumer, ConsumerGroup)
+- HTTPRoute is a special case in which the plugin is referenced as an extensionRef and not an annotation.
+
+## Global Plugins
+- A Kong Global Plugin maps to a KongClusterPlugin.
+- The plugin configuration is copied verbatim.
+
+## Consumer Group Plugin
+- A Kong Consumer Group plugin maps to a KongPlugin.
+- It's treated differently because the Kong Consumer Group plugin fields are different.
+
+# Consumer
+- A Consumer maps to a KongConsumer object.
+- Its credentials are mapped to Secrets in K8s.
+
+# Consumer Group
+- A Consumer Group is mapped to a KongConsumerGroup.
+
+# Certificate
+- A certificate is mapped to a Secret of type "kubernetes.io/tls".
+
+# CA Certificate
+- A CA Certificate maps to an Opaque Secret.
+
+# Upstream
+- An Upstream maps to a KongIngress for KIC v2 and to a KongUpstreamPolicy for KIC v3.
diff --git a/kong2kic/testdata/ca-certificate-input.yaml b/kong2kic/testdata/ca-certificate-input.yaml
new file mode 100644
index 000000000..c3c991e2a
--- /dev/null
+++ b/kong2kic/testdata/ca-certificate-input.yaml
@@ -0,0 +1,49 @@
+ca_certificates:
+- cert: |
+ -----BEGIN CERTIFICATE-----
+ MIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa
+ MBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw
+ NjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG
+ SM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx
+ 7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB
+ /wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2
+ ScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR
+ PSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ
+ -----END CERTIFICATE-----
+ cert_digest: f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5
+ id: 8ccca140-aff4-411d-8e1c-fcfb3f932a8e
+ tags:
+ - root-ca
+- cert: |
+ -----BEGIN CERTIFICATE-----
+ MIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow
+ GAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2
+ MTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0
+ ZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of
+ e0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM
+ o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E
+ FgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE
+ Q8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3
+ ZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl
+ -----END CERTIFICATE-----
+ cert_digest: dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308
+ id: 2e5f8ad1-21ca-47f5-8af7-899486e82731
+ tags:
+ - intermediate_ca1
+- cert: |
+ -----BEGIN CERTIFICATE-----
+ MIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo
+ MCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2
+ MTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS
+ b290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB
+ my/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws
+ Y9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw
+ BgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw
+ FoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc
+ azM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX
+ gxUhveuHBXMWnzUbn6U=
+ -----END CERTIFICATE-----
+ cert_digest: 45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600
+ id: cab2565d-fed6-4a07-b25c-bab76fdfe071
+ tags:
+ - intermediate_ca2
diff --git a/kong2kic/testdata/ca-certificate-output-expected.yaml b/kong2kic/testdata/ca-certificate-output-expected.yaml
new file mode 100644
index 000000000..e16719041
--- /dev/null
+++ b/kong2kic/testdata/ca-certificate-output-expected.yaml
@@ -0,0 +1,69 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ konghq.com/tags: root-ca
+ kubernetes.io/ingress.class: kong
+ name: ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf
+stringData:
+ ca.crt: |
+ -----BEGIN CERTIFICATE-----
+ MIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa
+ MBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw
+ NjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG
+ SM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx
+ 7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB
+ /wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2
+ ScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR
+ PSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ
+ -----END CERTIFICATE-----
+ ca.digest: f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5
+type: Opaque
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ konghq.com/tags: intermediate_ca1
+ kubernetes.io/ingress.class: kong
+ name: ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471
+stringData:
+ ca.crt: |
+ -----BEGIN CERTIFICATE-----
+ MIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow
+ GAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2
+ MTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0
+ ZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of
+ e0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM
+ o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E
+ FgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE
+ Q8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3
+ ZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl
+ -----END CERTIFICATE-----
+ ca.digest: dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308
+type: Opaque
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ konghq.com/tags: intermediate_ca2
+ kubernetes.io/ingress.class: kong
+ name: ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf
+stringData:
+ ca.crt: |
+ -----BEGIN CERTIFICATE-----
+ MIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo
+ MCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2
+ MTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS
+ b290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB
+ my/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws
+ Y9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw
+ BgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw
+ FoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc
+ azM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX
+ gxUhveuHBXMWnzUbn6U=
+ -----END CERTIFICATE-----
+ ca.digest: 45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600
+type: Opaque
+---
diff --git a/kong2kic/testdata/certificate-input.yaml b/kong2kic/testdata/certificate-input.yaml
new file mode 100644
index 000000000..b071d064e
--- /dev/null
+++ b/kong2kic/testdata/certificate-input.yaml
@@ -0,0 +1,146 @@
+certificates:
+- cert: |-
+ -----BEGIN CERTIFICATE-----
+ MIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL
+ BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
+ CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
+ MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
+ Z2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD
+ VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
+ EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy
+ b3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw
+ DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu
+ eLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD
+ /WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz
+ m5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F
+ uCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT
+ EP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA
+ AaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw
+ ADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI
+ hvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4
+ pJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS
+ GdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM
+ ovZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9
+ Fk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj
+ Ewxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=
+ -----END CERTIFICATE-----
+ id: 507cc555-5b92-496d-9e89-bfc78dfcddbe
+ key: |-
+ -----BEGIN PRIVATE KEY-----
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ
+ P+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi
+ 53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat
+ IoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q
+ XxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i
+ lIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy
+ E56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU
+ tyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda
+ DZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj
+ Dv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW
+ nYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5
+ RNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo
+ kQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/
+ zmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5
+ SrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C
+ 4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO
+ P0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu
+ reoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC
+ rDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI
+ kOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg
+ ECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm
+ zKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2
+ fXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu
+ LwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY
+ iVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3
+ NNSvLxPAempmiFPSk9AtobYV
+ -----END PRIVATE KEY-----
+ snis:
+ - name: proxy.kong.lan
+ tags:
+ - proxy.kong.lan
+- cert: |-
+ -----BEGIN CERTIFICATE-----
+ MIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL
+ BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
+ CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
+ MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
+ Z2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD
+ VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
+ EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10
+ bHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN
+ BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1
+ BYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo
+ byOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu
+ 3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z
+ 0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO
+ 1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa
+ 71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn
+ 3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2
+ OsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD
+ PgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj
+ vdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD
+ 55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE
+ AwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl
+ cnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME
+ GDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l
+ BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ
+ WELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY
+ I58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC
+ Xb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ
+ Ipmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa
+ aQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5
+ T8tqV6i5miKWwvfZ
+ -----END CERTIFICATE-----
+ id: f3ae1bb2-ea6a-4caf-a7a7-2f078b7842db
+ key: |-
+ -----BEGIN RSA PRIVATE KEY-----
+ MIIJKQIBAAKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1BYCn1+E9Uwgh0uwAenT/
+ DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTobyOUV6tIJAjvzyEOpC45
+ 8hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu3D6r8/zbhhWAqe4EIt+N
+ VYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z0xDqCSMmPebzjns03ttB
+ 29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO1mmABAQTQWMR/00+QI0x
+ tvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa71zNzARUVaZ2vy1pRVr0
+ DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn3M/roNLAU+3nz4itpt/z
+ f+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2OsqQuICaajnW7t1oDd7z
+ 1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywDPgnhSz9AaoVWhR+GHIPr
+ jRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAjvdLuNhx4bJbwLBgNGsJM
+ kupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD55NecBPNw5C9BR0CAwEA
+ AQKCAgEAymuOrG/hJKiS2oX8tm8eWFZIELI9BigYozYhCzQexpSGqjwEXOf1H5sB
+ 0YQjIAlZwhrc57OK7KpGZ6x2BgUT1JZZqs80CBtWxIXuuF5rpje7id8MTLCNuTzb
+ r+L2O4Mad0QNI5lKLH5mbt3yhiJ3NnQLHBpODjbpXGDFtTVne1hkJe5MfC1/psyt
+ wguO6HllcTTWl93ruonpZPtz39qhYuz4MCAnE5DRUrjO+Mn7y7XoyUS+xnSRl7BD
+ bqWRicJQyB+P7px3WyZQri+6TsCQ164iw2D64bLC1oCfLvLSBeh0g3gOdAX5mGTl
+ RBpf98LdFJXSmXHodcYMlO5THqHu7mOE8zvPDbOzpwKftE11PS+lhuq/fREJnrAx
+ pbvTkv2c1nu90gkracv6PhRC8YhBIa2gqhoxY7rH7UpYa1c5QaJzg5ibiteTLRKC
+ e9ZmfoPWaY2ksY4gBWZ/p2wokJ8U6ZHEsEfQS9WibMpqRsdINWQ9JnIBLKnTuqB0
+ B29E9jHAl8rwMT2/DiIiVjHcdwpP37MxotKvYDFw+yDcZDeKTIh133XZNWyO/TcH
+ aDrNB0dymqunuNmfPts566AYErym0ndcmmLuGIKKE+l1h1+5CWjdsTdrkkXZK/w1
+ i/krfLruQqQcW3Bpng8JAKirvGfYJxIEaCLqtepb7YaHhaI3gz0CggEBAPO0UQ6e
+ oPzMYmEegp2LjAfHZhwGV0fpiC6nxEWKoEE7Tb5zyB8rlkFIpQlXmljQvf3xDmq/
+ Ta3JlkaY290oFc0ypp9zUY/sUGyc3pvltxl0gLKOPnIkoP3ma2HzBxQRrGRdcFhH
+ AHom80Bm9APm29L0MFuOuhGGxkGvQCxH+KmmohvZMUEqNIuWi8XB7maDXcAmSJ7x
+ YdQAgLspRJ+kkZM+59XijyvYvg04xCu1FSop+Lol+xBwWAR5OaKnbZ9L+jKtzbxC
+ IS7ERTlhsham2dYIm7SFcD/OcLV6luqreR0svS6HQis1kGxnNxkBAbrB1QZ+wLKp
+ QztnOk70H/eWP5sCggEBAOLllCHuRloqEyzDT5sVbflCMTVsXmHGJ4/qI4An+etI
+ 3DComNLPAIBKYAiNgqWAm/wfLy5rHu2ZGzcPn7cQF/xKp00uDGKncQz3Z9JDofI1
+ rpLH+t3LJ9l/EzQv1tpzwOU5rhFNmqrJnwy17BtOmlCKAQnVmyDkLyR9AhWkCTi8
+ BLDq6mx1X61K6P11GAxAd70NFNzD8868Ddq2XInwEwXzf/FHQW/JVYZEAa7dn4KF
+ wQ/tPSspP0vGzDfgNI64PtNePnZ/e00XXqA7la2OScro+SDSyXGlDKX4XhwwTDD1
+ +u3VbUmjInpEJL3bU8c/qe36UhoseF1G0cm22sHqhacCggEAY3A+5r05KQ1oUwJ0
+ /z2ybHYjJuo7cN9MLuVLg6iVzSgah8yMapOJYqf2l0JEe1rpOxXB8TKPyoqHo9S5
+ WZsCklDJhiQysowVIMw9VNU9ichsvu6lckOZ4R/Ezxmv2LOBaQ5rScnm2vDLroqT
+ pIftSD1VAfbR21bnzGNqxuazAt44JS7RFyrWd+J8s7t2wCN3/HBij2Akr7Fo1XV4
+ R7+JmtA/HpmsG5L7sT9pZAAmW6b2k1XuBH4im+iu6LxyUV5Z/5XFbbx597AkIs7H
+ MNDx75BhoB4WeCKPAK29qJFBAPOBWdvc1u6rOGBBLhWoFAEFH/pWPFAuW626L/8S
+ kB6hYwKCAQB3/JIec2Pu0Gs9c7eIOofilXdyWfF7YQ+Q0m+dmQZXvzr53F6ctGz+
+ atZoD3V0UhOq+063DFzZpuq2bmO2qiMU/uGENgLEtOlawwa7MZrVfD/qTSjD22gi
+ Y0njghzrfuUWEy+S5OgSwvaCAT5vnlyKlMBB1BzqAuFPOXA9w3ZA82TDribz3goP
+ mRqm1iI2cG0ho2ZR7KnkvJvS+jbrlvJoZkFVdaoMFHtOum3tbDOrEVJsOrfrOC/J
+ wcJDFiSVCKfonOEJRxcMSHx43amkkydAz3zXN8DhgTe0GSijXYMdLSdaWFAn7cYQ
+ xDJt2CtwpaEWQRbj0nqAUTAlrLX4cC3nAoIBAQCl1cV86bYw8CKrCuf9TF0Kk5pd
+ REdilDpks4Z1RH4MpBDWLtvMeQqlNsN+/RugKQExO0HTdZIyn7cBRRloD2xcNcJA
+ G/rUMel/x4fhaEOE7Uw9rmTefvpcgWmtXw64sMA8KFA4oCXIcgbwL5Q+szqNNWAN
+ abpgl0DnU06YyBDoK/7D0B8Kt3qS1N6XX+Z5wtPvglbD2HCYy6rdkqi8IbQ/6OeS
+ wG7p/7g3JlOEyotMq9Cl2T0wTNDSLlma+mwc9mILITDXznWiLQSznE69mebWBUr3
+ Sbt91efH30inRx85H0pNJrpZsH0A6ayL0gTJSuUc0eJXYR5Po1gRQMOSIEWh
+ -----END RSA PRIVATE KEY-----
\ No newline at end of file
diff --git a/kong2kic/testdata/certificate-output-expected.yaml b/kong2kic/testdata/certificate-output-expected.yaml
new file mode 100644
index 000000000..744685098
--- /dev/null
+++ b/kong2kic/testdata/certificate-output-expected.yaml
@@ -0,0 +1,158 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ konghq.com/tags: proxy.kong.lan
+ kubernetes.io/ingress.class: kong
+ name: cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e
+stringData:
+ tls.crt: |-
+ -----BEGIN CERTIFICATE-----
+ MIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL
+ BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
+ CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
+ MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
+ Z2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD
+ VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
+ EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy
+ b3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw
+ DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu
+ eLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD
+ /WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz
+ m5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F
+ uCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT
+ EP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA
+ AaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw
+ ADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI
+ hvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4
+ pJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS
+ GdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM
+ ovZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9
+ Fk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj
+ Ewxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=
+ -----END CERTIFICATE-----
+ tls.key: |-
+ -----BEGIN PRIVATE KEY-----
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ
+ P+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi
+ 53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat
+ IoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q
+ XxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i
+ lIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy
+ E56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU
+ tyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda
+ DZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj
+ Dv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW
+ nYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5
+ RNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo
+ kQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/
+ zmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5
+ SrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C
+ 4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO
+ P0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu
+ reoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC
+ rDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI
+ kOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg
+ ECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm
+ zKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2
+ fXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu
+ LwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY
+ iVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3
+ NNSvLxPAempmiFPSk9AtobYV
+ -----END PRIVATE KEY-----
+type: kubernetes.io/tls
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323
+stringData:
+ tls.crt: |-
+ -----BEGIN CERTIFICATE-----
+ MIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL
+ BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
+ CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
+ MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
+ Z2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD
+ VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
+ EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10
+ bHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN
+ BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1
+ BYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo
+ byOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu
+ 3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z
+ 0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO
+ 1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa
+ 71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn
+ 3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2
+ OsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD
+ PgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj
+ vdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD
+ 55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE
+ AwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl
+ cnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME
+ GDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l
+ BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ
+ WELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY
+ I58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC
+ Xb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ
+ Ipmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa
+ aQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5
+ T8tqV6i5miKWwvfZ
+ -----END CERTIFICATE-----
+ tls.key: |-
+ -----BEGIN RSA PRIVATE KEY-----
+ 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
+ -----END RSA PRIVATE KEY-----
+type: kubernetes.io/tls
+---
diff --git a/kong2kic/testdata/consumer-group-input.yaml b/kong2kic/testdata/consumer-group-input.yaml
new file mode 100644
index 000000000..69bba14ec
--- /dev/null
+++ b/kong2kic/testdata/consumer-group-input.yaml
@@ -0,0 +1,19 @@
+consumers:
+ - username: example-consumer-group-user
+ tags:
+ - internal
+consumer_groups:
+ - name: example-consumer-group
+ consumers:
+ - username: example-consumer-group-user
+ plugins:
+ - name: rate-limiting
+ config:
+ second: 5
+ hour: 10000
+ policy: local
+ tags:
+ - internal-gold-users
+
+
+
\ No newline at end of file
diff --git a/kong2kic/testdata/consumer-group-output-expected.yaml b/kong2kic/testdata/consumer-group-output-expected.yaml
new file mode 100644
index 000000000..1f2f93ebf
--- /dev/null
+++ b/kong2kic/testdata/consumer-group-output-expected.yaml
@@ -0,0 +1,32 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ hour: 10000
+ policy: local
+ second: 5
+kind: KongPlugin
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: example-consumer-group-rate-limiting
+plugin: rate-limiting
+---
+apiVersion: configuration.konghq.com/v1
+consumerGroups:
+- example-consumer-group
+kind: KongConsumer
+metadata:
+ annotations:
+ konghq.com/tags: internal
+ kubernetes.io/ingress.class: kong
+ name: example-consumer-group-user
+username: example-consumer-group-user
+---
+apiVersion: configuration.konghq.com/v1beta1
+kind: KongConsumerGroup
+metadata:
+ annotations:
+ konghq.com/plugins: example-consumer-group-rate-limiting
+ konghq.com/tags: internal-gold-users
+ kubernetes.io/ingress.class: kong
+ name: example-consumer-group
+---
diff --git a/kong2kic/testdata/consumer-input.yaml b/kong2kic/testdata/consumer-input.yaml
new file mode 100644
index 000000000..ce86e6e33
--- /dev/null
+++ b/kong2kic/testdata/consumer-input.yaml
@@ -0,0 +1,43 @@
+consumers:
+ - username: example-user
+ custom_id: "1234567890"
+ tags:
+ - internal
+ acls:
+ - group: acl_group
+ tags:
+ - internal
+ basicauth_credentials:
+ - username: my_basic_user
+ password: my_basic_password
+ tags:
+ - internal
+ jwt_secrets:
+ - key: my_jwt_secret
+ algorithm: HS256
+ secret: my_secret_key
+ rsa_public_key: |-
+ -----BEGIN PUBLIC KEY-----
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX
+ ZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3
+ oWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4
+ 4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ
+ DfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw
+ O/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6
+ ewIDAQAB
+ -----END PUBLIC KEY-----
+ tags:
+ - internal
+ keyauth_credentials:
+ - key: my_api_key
+ tags:
+ - internal
+ mtls_auth_credentials:
+ - id: cce8c384-721f-4f58-85dd-50834e3e733a
+ subject_name: example-user@example.com
+ plugins:
+ - name: rate-limiting
+ config:
+ second: 5
+ hour: 10000
+ policy: local
\ No newline at end of file
diff --git a/kong2kic/testdata/consumer-v2-output-expected.yaml b/kong2kic/testdata/consumer-v2-output-expected.yaml
new file mode 100644
index 000000000..9978ab114
--- /dev/null
+++ b/kong2kic/testdata/consumer-v2-output-expected.yaml
@@ -0,0 +1,94 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ hour: 10000
+ policy: local
+ second: 5
+kind: KongPlugin
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: example-user-rate-limiting
+plugin: rate-limiting
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: key-auth-example-user
+stringData:
+ key: my_api_key
+ kongCredType: key-auth
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: jwt-auth-example-user
+stringData:
+ algorithm: HS256
+ key: my_jwt_secret
+ kongCredType: jwt
+ rsa_public_key: |-
+ -----BEGIN PUBLIC KEY-----
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX
+ ZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3
+ oWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4
+ 4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ
+ DfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw
+ O/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6
+ ewIDAQAB
+ -----END PUBLIC KEY-----
+ secret: my_secret_key
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: basic-auth-example-user
+stringData:
+ kongCredType: basic-auth
+ password: my_basic_password
+ username: my_basic_user
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: acl-group-example-user
+stringData:
+ group: acl_group
+ kongCredType: acl
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: mtls-auth-example-user
+stringData:
+ id: cce8c384-721f-4f58-85dd-50834e3e733a
+ kongCredType: mtls-auth
+ subject_name: example-user@example.com
+type: Opaque
+---
+apiVersion: configuration.konghq.com/v1
+credentials:
+- key-auth-example-user
+- jwt-auth-example-user
+- basic-auth-example-user
+- acl-group-example-user
+- mtls-auth-example-user
+custom_id: "1234567890"
+kind: KongConsumer
+metadata:
+ annotations:
+ konghq.com/plugins: example-user-rate-limiting
+ konghq.com/tags: internal
+ kubernetes.io/ingress.class: kong
+ name: example-user
+username: example-user
+---
diff --git a/kong2kic/testdata/consumer-v3-output-expected.yaml b/kong2kic/testdata/consumer-v3-output-expected.yaml
new file mode 100644
index 000000000..6e843caad
--- /dev/null
+++ b/kong2kic/testdata/consumer-v3-output-expected.yaml
@@ -0,0 +1,99 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ hour: 10000
+ policy: local
+ second: 5
+kind: KongPlugin
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: example-user-rate-limiting
+plugin: rate-limiting
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ labels:
+ konghq.com/credential: key-auth
+ name: key-auth-example-user
+stringData:
+ key: my_api_key
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ labels:
+ konghq.com/credential: jwt
+ name: jwt-auth-example-user
+stringData:
+ algorithm: HS256
+ key: my_jwt_secret
+ rsa_public_key: |-
+ -----BEGIN PUBLIC KEY-----
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX
+ ZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3
+ oWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4
+ 4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ
+ DfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw
+ O/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6
+ ewIDAQAB
+ -----END PUBLIC KEY-----
+ secret: my_secret_key
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ labels:
+ konghq.com/credential: basic-auth
+ name: basic-auth-example-user
+stringData:
+ password: my_basic_password
+ username: my_basic_user
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ labels:
+ konghq.com/credential: acl
+ name: acl-group-example-user
+stringData:
+ group: acl_group
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ labels:
+ konghq.com/credential: mtls-auth
+ name: mtls-auth-example-user
+stringData:
+ id: cce8c384-721f-4f58-85dd-50834e3e733a
+ subject_name: example-user@example.com
+type: Opaque
+---
+apiVersion: configuration.konghq.com/v1
+credentials:
+- key-auth-example-user
+- jwt-auth-example-user
+- basic-auth-example-user
+- acl-group-example-user
+- mtls-auth-example-user
+custom_id: "1234567890"
+kind: KongConsumer
+metadata:
+ annotations:
+ konghq.com/plugins: example-user-rate-limiting
+ konghq.com/tags: internal
+ kubernetes.io/ingress.class: kong
+ name: example-user
+username: example-user
+---
diff --git a/kong2kic/testdata/gateway-api-crd.yaml b/kong2kic/testdata/gateway-api-crd.yaml
new file mode 100644
index 000000000..ef536cb90
--- /dev/null
+++ b/kong2kic/testdata/gateway-api-crd.yaml
@@ -0,0 +1,7137 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466
+ gateway.networking.k8s.io/bundle-version: v1.0.0
+ gateway.networking.k8s.io/channel: standard
+ creationTimestamp: null
+ name: gatewayclasses.gateway.networking.k8s.io
+spec:
+ group: gateway.networking.k8s.io
+ names:
+ categories:
+ - gateway-api
+ kind: GatewayClass
+ listKind: GatewayClassList
+ plural: gatewayclasses
+ shortNames:
+ - gc
+ singular: gatewayclass
+ scope: Cluster
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.controllerName
+ name: Controller
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Accepted")].status
+ name: Accepted
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ - jsonPath: .spec.description
+ name: Description
+ priority: 1
+ type: string
+ name: v1
+ schema:
+ openAPIV3Schema:
+ description: "GatewayClass describes a class of Gateways available to the
+ user for creating Gateway resources. \n It is recommended that this resource
+ be used as a template for Gateways. This means that a Gateway is based on
+ the state of the GatewayClass at the time it was created and changes to
+ the GatewayClass or associated parameters are not propagated down to existing
+ Gateways. This recommendation is intended to limit the blast radius of changes
+ to GatewayClass or associated parameters. If implementations choose to propagate
+ GatewayClass changes to existing Gateways, that MUST be clearly documented
+ by the implementation. \n Whenever one or more Gateways are using a GatewayClass,
+ implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io`
+ finalizer on the associated GatewayClass. This ensures that a GatewayClass
+ associated with a Gateway is not deleted while in use. \n GatewayClass is
+ a Cluster level resource."
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of GatewayClass.
+ properties:
+ controllerName:
+ description: "ControllerName is the name of the controller that is
+ managing Gateways of this class. The value of this field MUST be
+ a domain prefixed path. \n Example: \"example.net/gateway-controller\".
+ \n This field is not mutable and cannot be empty. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ x-kubernetes-validations:
+ - message: Value is immutable
+ rule: self == oldSelf
+ description:
+ description: Description helps describe a GatewayClass with more details.
+ maxLength: 64
+ type: string
+ parametersRef:
+ description: "ParametersRef is a reference to a resource that contains
+ the configuration parameters corresponding to the GatewayClass.
+ This is optional if the controller does not require any additional
+ configuration. \n ParametersRef can reference a standard Kubernetes
+ resource, i.e. ConfigMap, or an implementation-specific custom resource.
+ The resource can be cluster-scoped or namespace-scoped. \n If the
+ referent cannot be found, the GatewayClass's \"InvalidParameters\"
+ status condition will be true. \n Support: Implementation-specific"
+ properties:
+ group:
+ description: Group is the group of the referent.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is kind of the referent.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: Namespace is the namespace of the referent. This
+ field is required when referring to a Namespace-scoped resource
+ and MUST be unset when referring to a Cluster-scoped resource.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ required:
+ - group
+ - kind
+ - name
+ type: object
+ required:
+ - controllerName
+ type: object
+ status:
+ default:
+ conditions:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Waiting
+ status: Unknown
+ type: Accepted
+ description: "Status defines the current state of GatewayClass. \n Implementations
+ MUST populate status on all GatewayClass resources which specify their
+ controller name."
+ properties:
+ conditions:
+ default:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Accepted
+ description: "Conditions is the current status from the controller
+ for this GatewayClass. \n Controllers should prefer to publish conditions
+ using values of GatewayClassConditionType for the type of each Condition."
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended for direct
+ use as an array at the field path .status.conditions. For example,
+ \n type FooStatus struct{ // Represents the observations of a
+ foo's current state. // Known .status.conditions.type are: \"Available\",
+ \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should be when
+ the underlying condition changed. If that is not known, then
+ using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance, if .metadata.generation
+ is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating
+ the reason for the condition's last transition. Producers
+ of specific condition types may define expected values and
+ meanings for this field, and whether the values are considered
+ a guaranteed API. The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across resources
+ like Available, but because arbitrary conditions can be useful
+ (see .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
+ - additionalPrinterColumns:
+ - jsonPath: .spec.controllerName
+ name: Controller
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Accepted")].status
+ name: Accepted
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ - jsonPath: .spec.description
+ name: Description
+ priority: 1
+ type: string
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: "GatewayClass describes a class of Gateways available to the
+ user for creating Gateway resources. \n It is recommended that this resource
+ be used as a template for Gateways. This means that a Gateway is based on
+ the state of the GatewayClass at the time it was created and changes to
+ the GatewayClass or associated parameters are not propagated down to existing
+ Gateways. This recommendation is intended to limit the blast radius of changes
+ to GatewayClass or associated parameters. If implementations choose to propagate
+ GatewayClass changes to existing Gateways, that MUST be clearly documented
+ by the implementation. \n Whenever one or more Gateways are using a GatewayClass,
+ implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io`
+ finalizer on the associated GatewayClass. This ensures that a GatewayClass
+ associated with a Gateway is not deleted while in use. \n GatewayClass is
+ a Cluster level resource."
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of GatewayClass.
+ properties:
+ controllerName:
+ description: "ControllerName is the name of the controller that is
+ managing Gateways of this class. The value of this field MUST be
+ a domain prefixed path. \n Example: \"example.net/gateway-controller\".
+ \n This field is not mutable and cannot be empty. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ x-kubernetes-validations:
+ - message: Value is immutable
+ rule: self == oldSelf
+ description:
+ description: Description helps describe a GatewayClass with more details.
+ maxLength: 64
+ type: string
+ parametersRef:
+ description: "ParametersRef is a reference to a resource that contains
+ the configuration parameters corresponding to the GatewayClass.
+ This is optional if the controller does not require any additional
+ configuration. \n ParametersRef can reference a standard Kubernetes
+ resource, i.e. ConfigMap, or an implementation-specific custom resource.
+ The resource can be cluster-scoped or namespace-scoped. \n If the
+ referent cannot be found, the GatewayClass's \"InvalidParameters\"
+ status condition will be true. \n Support: Implementation-specific"
+ properties:
+ group:
+ description: Group is the group of the referent.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is kind of the referent.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: Namespace is the namespace of the referent. This
+ field is required when referring to a Namespace-scoped resource
+ and MUST be unset when referring to a Cluster-scoped resource.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ required:
+ - group
+ - kind
+ - name
+ type: object
+ required:
+ - controllerName
+ type: object
+ status:
+ default:
+ conditions:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Waiting
+ status: Unknown
+ type: Accepted
+ description: "Status defines the current state of GatewayClass. \n Implementations
+ MUST populate status on all GatewayClass resources which specify their
+ controller name."
+ properties:
+ conditions:
+ default:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Accepted
+ description: "Conditions is the current status from the controller
+ for this GatewayClass. \n Controllers should prefer to publish conditions
+ using values of GatewayClassConditionType for the type of each Condition."
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended for direct
+ use as an array at the field path .status.conditions. For example,
+ \n type FooStatus struct{ // Represents the observations of a
+ foo's current state. // Known .status.conditions.type are: \"Available\",
+ \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should be when
+ the underlying condition changed. If that is not known, then
+ using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance, if .metadata.generation
+ is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating
+ the reason for the condition's last transition. Producers
+ of specific condition types may define expected values and
+ meanings for this field, and whether the values are considered
+ a guaranteed API. The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across resources
+ like Available, but because arbitrary conditions can be useful
+ (see .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+status:
+ acceptedNames:
+ kind: ""
+ plural: ""
+ conditions: null
+ storedVersions: null
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466
+ gateway.networking.k8s.io/bundle-version: v1.0.0
+ gateway.networking.k8s.io/channel: standard
+ creationTimestamp: null
+ name: gateways.gateway.networking.k8s.io
+spec:
+ group: gateway.networking.k8s.io
+ names:
+ categories:
+ - gateway-api
+ kind: Gateway
+ listKind: GatewayList
+ plural: gateways
+ shortNames:
+ - gtw
+ singular: gateway
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.gatewayClassName
+ name: Class
+ type: string
+ - jsonPath: .status.addresses[*].value
+ name: Address
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Programmed")].status
+ name: Programmed
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1
+ schema:
+ openAPIV3Schema:
+ description: Gateway represents an instance of a service-traffic handling
+ infrastructure by binding Listeners to a set of IP addresses.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of Gateway.
+ properties:
+ addresses:
+ description: "Addresses requested for this Gateway. This is optional
+ and behavior can depend on the implementation. If a value is set
+ in the spec and the requested address is invalid or unavailable,
+ the implementation MUST indicate this in the associated entry in
+ GatewayStatus.Addresses. \n The Addresses field represents a request
+ for the address(es) on the \"outside of the Gateway\", that traffic
+ bound for this Gateway will use. This could be the IP address or
+ hostname of an external load balancer or other networking infrastructure,
+ or some other address that traffic will be sent to. \n If no Addresses
+ are specified, the implementation MAY schedule the Gateway in an
+ implementation-specific manner, assigning an appropriate set of
+ Addresses. \n The implementation MUST bind all Listeners to every
+ GatewayAddress that it assigns to the Gateway and add a corresponding
+ entry in GatewayStatus.Addresses. \n Support: Extended \n "
+ items:
+ description: GatewayAddress describes an address that can be bound
+ to a Gateway.
+ oneOf:
+ - properties:
+ type:
+ enum:
+ - IPAddress
+ value:
+ anyOf:
+ - format: ipv4
+ - format: ipv6
+ - properties:
+ type:
+ not:
+ enum:
+ - IPAddress
+ properties:
+ type:
+ default: IPAddress
+ description: Type of the address.
+ maxLength: 253
+ minLength: 1
+ pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ value:
+ description: "Value of the address. The validity of the values
+ will depend on the type and support by the controller. \n
+ Examples: `1.2.3.4`, `128::1`, `my-ip-address`."
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - value
+ type: object
+ x-kubernetes-validations:
+ - message: Hostname value must only contain valid characters (matching
+ ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)
+ rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""):
+ true'
+ maxItems: 16
+ type: array
+ x-kubernetes-validations:
+ - message: IPAddress values must be unique
+ rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2,
+ a2.type == a1.type && a2.value == a1.value) : true )'
+ - message: Hostname values must be unique
+ rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2,
+ a2.type == a1.type && a2.value == a1.value) : true )'
+ gatewayClassName:
+ description: GatewayClassName used for this Gateway. This is the name
+ of a GatewayClass resource.
+ maxLength: 253
+ minLength: 1
+ type: string
+ listeners:
+ description: "Listeners associated with this Gateway. Listeners define
+ logical endpoints that are bound on this Gateway's addresses. At
+ least one Listener MUST be specified. \n Each Listener in a set
+ of Listeners (for example, in a single Gateway) MUST be _distinct_,
+ in that a traffic flow MUST be able to be assigned to exactly one
+ listener. (This section uses \"set of Listeners\" rather than \"Listeners
+ in a single Gateway\" because implementations MAY merge configuration
+ from multiple Gateways onto a single data plane, and these rules
+ _also_ apply in that case). \n Practically, this means that each
+ listener in a set MUST have a unique combination of Port, Protocol,
+ and, if supported by the protocol, Hostname. \n Some combinations
+ of port, protocol, and TLS settings are considered Core support
+ and MUST be supported by implementations based on their targeted
+ conformance profile: \n HTTP Profile \n 1. HTTPRoute, Port: 80,
+ Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode:
+ Terminate, TLS keypair provided \n TLS Profile \n 1. TLSRoute, Port:
+ 443, Protocol: TLS, TLS Mode: Passthrough \n \"Distinct\" Listeners
+ have the following property: \n The implementation can match inbound
+ requests to a single distinct Listener. When multiple Listeners
+ share values for fields (for example, two Listeners with the same
+ Port value), the implementation can match requests to only one of
+ the Listeners using other Listener fields. \n For example, the following
+ Listener scenarios are distinct: \n 1. Multiple Listeners with the
+ same Port that all use the \"HTTP\" Protocol that all have unique
+ Hostname values. 2. Multiple Listeners with the same Port that use
+ either the \"HTTPS\" or \"TLS\" Protocol that all have unique Hostname
+ values. 3. A mixture of \"TCP\" and \"UDP\" Protocol Listeners,
+ where no Listener with the same Protocol has the same Port value.
+ \n Some fields in the Listener struct have possible values that
+ affect whether the Listener is distinct. Hostname is particularly
+ relevant for HTTP or HTTPS protocols. \n When using the Hostname
+ value to select between same-Port, same-Protocol Listeners, the
+ Hostname value must be different on each Listener for the Listener
+ to be distinct. \n When the Listeners are distinct based on Hostname,
+ inbound request hostnames MUST match from the most specific to least
+ specific Hostname values to choose the correct Listener and its
+ associated set of Routes. \n Exact matches must be processed before
+ wildcard matches, and wildcard matches must be processed before
+ fallback (empty Hostname value) matches. For example, `\"foo.example.com\"`
+ takes precedence over `\"*.example.com\"`, and `\"*.example.com\"`
+ takes precedence over `\"\"`. \n Additionally, if there are multiple
+ wildcard entries, more specific wildcard entries must be processed
+ before less specific wildcard entries. For example, `\"*.foo.example.com\"`
+ takes precedence over `\"*.example.com\"`. The precise definition
+ here is that the higher the number of dots in the hostname to the
+ right of the wildcard character, the higher the precedence. \n The
+ wildcard character will match any number of characters _and dots_
+ to the left, however, so `\"*.example.com\"` will match both `\"foo.bar.example.com\"`
+ _and_ `\"bar.example.com\"`. \n If a set of Listeners contains Listeners
+ that are not distinct, then those Listeners are Conflicted, and
+ the implementation MUST set the \"Conflicted\" condition in the
+ Listener Status to \"True\". \n Implementations MAY choose to accept
+ a Gateway with some Conflicted Listeners only if they only accept
+ the partial Listener set that contains no Conflicted Listeners.
+ To put this another way, implementations may accept a partial Listener
+ set only if they throw out *all* the conflicting Listeners. No picking
+ one of the conflicting listeners as the winner. This also means
+ that the Gateway must have at least one non-conflicting Listener
+ in this case, otherwise it violates the requirement that at least
+ one Listener must be present. \n The implementation MUST set a \"ListenersNotValid\"
+ condition on the Gateway Status when the Gateway contains Conflicted
+ Listeners whether or not they accept the Gateway. That Condition
+ SHOULD clearly indicate in the Message which Listeners are conflicted,
+ and which are Accepted. Additionally, the Listener status for those
+ listeners SHOULD indicate which Listeners are conflicted and not
+ Accepted. \n A Gateway's Listeners are considered \"compatible\"
+ if: \n 1. They are distinct. 2. The implementation can serve them
+ in compliance with the Addresses requirement that all Listeners
+ are available on all assigned addresses. \n Compatible combinations
+ in Extended support are expected to vary across implementations.
+ A combination that is compatible for one implementation may not
+ be compatible for another. \n For example, an implementation that
+ cannot serve both TCP and UDP listeners on the same address, or
+ cannot mix HTTPS and generic TLS listens on the same port would
+ not consider those cases compatible, even though they are distinct.
+ \n Note that requests SHOULD match at most one Listener. For example,
+ if Listeners are defined for \"foo.example.com\" and \"*.example.com\",
+ a request to \"foo.example.com\" SHOULD only be routed using routes
+ attached to the \"foo.example.com\" Listener (and not the \"*.example.com\"
+ Listener). This concept is known as \"Listener Isolation\". Implementations
+ that do not support Listener Isolation MUST clearly document this.
+ \n Implementations MAY merge separate Gateways onto a single set
+ of Addresses if all Listeners across all Gateways are compatible.
+ \n Support: Core"
+ items:
+ description: Listener embodies the concept of a logical endpoint
+ where a Gateway accepts network connections.
+ properties:
+ allowedRoutes:
+ default:
+ namespaces:
+ from: Same
+ description: "AllowedRoutes defines the types of routes that
+ MAY be attached to a Listener and the trusted namespaces where
+ those Route resources MAY be present. \n Although a client
+ request may match multiple route rules, only one rule may
+ ultimately receive the request. Matching precedence MUST be
+ determined in order of the following criteria: \n * The most
+ specific match as defined by the Route type. * The oldest
+ Route based on creation timestamp. For example, a Route with
+ a creation timestamp of \"2020-09-08 01:02:03\" is given precedence
+ over a Route with a creation timestamp of \"2020-09-08 01:02:04\".
+ * If everything else is equivalent, the Route appearing first
+ in alphabetical order (namespace/name) should be given precedence.
+ For example, foo/bar is given precedence over foo/baz. \n
+ All valid rules within a Route attached to this Listener should
+ be implemented. Invalid Route rules can be ignored (sometimes
+ that will mean the full Route). If a Route rule transitions
+ from valid to invalid, support for that Route rule should
+ be dropped to ensure consistency. For example, even if a filter
+ specified by a Route rule is invalid, the rest of the rules
+ within that Route should still be supported. \n Support: Core"
+ properties:
+ kinds:
+ description: "Kinds specifies the groups and kinds of Routes
+ that are allowed to bind to this Gateway Listener. When
+ unspecified or empty, the kinds of Routes selected are
+ determined using the Listener protocol. \n A RouteGroupKind
+ MUST correspond to kinds of Routes that are compatible
+ with the application protocol specified in the Listener's
+ Protocol field. If an implementation does not support
+ or recognize this resource type, it MUST set the \"ResolvedRefs\"
+ condition to False for this Listener with the \"InvalidRouteKinds\"
+ reason. \n Support: Core"
+ items:
+ description: RouteGroupKind indicates the group and kind
+ of a Route resource.
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: Group is the group of the Route.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is the kind of the Route.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ required:
+ - kind
+ type: object
+ maxItems: 8
+ type: array
+ namespaces:
+ default:
+ from: Same
+ description: "Namespaces indicates namespaces from which
+ Routes may be attached to this Listener. This is restricted
+ to the namespace of this Gateway by default. \n Support:
+ Core"
+ properties:
+ from:
+ default: Same
+ description: "From indicates where Routes will be selected
+ for this Gateway. Possible values are: \n * All: Routes
+ in all namespaces may be used by this Gateway. * Selector:
+ Routes in namespaces selected by the selector may
+ be used by this Gateway. * Same: Only Routes in the
+ same namespace may be used by this Gateway. \n Support:
+ Core"
+ enum:
+ - All
+ - Selector
+ - Same
+ type: string
+ selector:
+ description: "Selector must be specified when From is
+ set to \"Selector\". In that case, only Routes in
+ Namespaces matching this Selector will be selected
+ by this Gateway. This field is ignored for other values
+ of \"From\". \n Support: Core"
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are ANDed.
+ items:
+ description: A label selector requirement is a
+ selector that contains values, a key, and an
+ operator that relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the
+ selector applies to.
+ type: string
+ operator:
+ description: operator represents a key's relationship
+ to a set of values. Valid operators are
+ In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: values is an array of string
+ values. If the operator is In or NotIn,
+ the values array must be non-empty. If the
+ operator is Exists or DoesNotExist, the
+ values array must be empty. This array is
+ replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: matchLabels is a map of {key,value}
+ pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions,
+ whose key field is "key", the operator is "In",
+ and the values array contains only "value". The
+ requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ type: object
+ hostname:
+ description: "Hostname specifies the virtual hostname to match
+ for protocol types that define this concept. When unspecified,
+ all hostnames are matched. This field is ignored for protocols
+ that don't require hostname based matching. \n Implementations
+ MUST apply Hostname matching appropriately for each of the
+ following protocols: \n * TLS: The Listener Hostname MUST
+ match the SNI. * HTTP: The Listener Hostname MUST match the
+ Host header of the request. * HTTPS: The Listener Hostname
+ SHOULD match at both the TLS and HTTP protocol layers as described
+ above. If an implementation does not ensure that both the
+ SNI and Host header match the Listener hostname, it MUST clearly
+ document that. \n For HTTPRoute and TLSRoute resources, there
+ is an interaction with the `spec.hostnames` array. When both
+ listener and route specify hostnames, there MUST be an intersection
+ between the values for a Route to be accepted. For more information,
+ refer to the Route specific Hostnames documentation. \n Hostnames
+ that are prefixed with a wildcard label (`*.`) are interpreted
+ as a suffix match. That means that a match for `*.example.com`
+ would match both `test.example.com`, and `foo.test.example.com`,
+ but not `example.com`. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ name:
+ description: "Name is the name of the Listener. This name MUST
+ be unique within a Gateway. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ port:
+ description: "Port is the network port. Multiple listeners may
+ use the same port, subject to the Listener compatibility rules.
+ \n Support: Core"
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ protocol:
+ description: "Protocol specifies the network protocol this listener
+ expects to receive. \n Support: Core"
+ maxLength: 255
+ minLength: 1
+ pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$
+ type: string
+ tls:
+ description: "TLS is the TLS configuration for the Listener.
+ This field is required if the Protocol field is \"HTTPS\"
+ or \"TLS\". It is invalid to set this field if the Protocol
+ field is \"HTTP\", \"TCP\", or \"UDP\". \n The association
+ of SNIs to Certificate defined in GatewayTLSConfig is defined
+ based on the Hostname field for this listener. \n The GatewayClass
+ MUST use the longest matching SNI out of all available certificates
+ for any TLS handshake. \n Support: Core"
+ properties:
+ certificateRefs:
+ description: "CertificateRefs contains a series of references
+ to Kubernetes objects that contains TLS certificates and
+ private keys. These certificates are used to establish
+ a TLS handshake for requests that match the hostname of
+ the associated listener. \n A single CertificateRef to
+ a Kubernetes Secret has \"Core\" support. Implementations
+ MAY choose to support attaching multiple certificates
+ to a Listener, but this behavior is implementation-specific.
+ \n References to a resource in different namespace are
+ invalid UNLESS there is a ReferenceGrant in the target
+ namespace that allows the certificate to be attached.
+ If a ReferenceGrant does not allow this reference, the
+ \"ResolvedRefs\" condition MUST be set to False for this
+ listener with the \"RefNotPermitted\" reason. \n This
+ field is required to have at least one element when the
+ mode is set to \"Terminate\" (default) and is optional
+ otherwise. \n CertificateRefs can reference to standard
+ Kubernetes resources, i.e. Secret, or implementation-specific
+ custom resources. \n Support: Core - A single reference
+ to a Kubernetes Secret of type kubernetes.io/tls \n Support:
+ Implementation-specific (More than one reference or other
+ resource types)"
+ items:
+ description: "SecretObjectReference identifies an API
+ object including its namespace, defaulting to Secret.
+ \n The API object must be valid in the cluster; the
+ Group and Kind must be registered in the cluster for
+ this reference to be valid. \n References to objects
+ with invalid Group and Kind are not valid, and must
+ be rejected by the implementation, with appropriate
+ Conditions set on the containing object."
+ properties:
+ group:
+ default: ""
+ description: Group is the group of the referent. For
+ example, "gateway.networking.k8s.io". When unspecified
+ or empty string, core API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Secret
+ description: Kind is kind of the referent. For example
+ "Secret".
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referenced
+ object. When unspecified, the local namespace is
+ inferred. \n Note that when a namespace different
+ than the local namespace is specified, a ReferenceGrant
+ object is required in the referent namespace to
+ allow that namespace's owner to accept the reference.
+ See the ReferenceGrant documentation for details.
+ \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ required:
+ - name
+ type: object
+ maxItems: 64
+ type: array
+ mode:
+ default: Terminate
+ description: "Mode defines the TLS behavior for the TLS
+ session initiated by the client. There are two possible
+ modes: \n - Terminate: The TLS session between the downstream
+ client and the Gateway is terminated at the Gateway. This
+ mode requires certificateRefs to be set and contain at
+ least one element. - Passthrough: The TLS session is NOT
+ terminated by the Gateway. This implies that the Gateway
+ can't decipher the TLS stream except for the ClientHello
+ message of the TLS protocol. CertificateRefs field is
+ ignored in this mode. \n Support: Core"
+ enum:
+ - Terminate
+ - Passthrough
+ type: string
+ options:
+ additionalProperties:
+ description: AnnotationValue is the value of an annotation
+ in Gateway API. This is used for validation of maps
+ such as TLS options. This roughly matches Kubernetes
+ annotation validation, although the length validation
+ in that case is based on the entire size of the annotations
+ struct.
+ maxLength: 4096
+ minLength: 0
+ type: string
+ description: "Options are a list of key/value pairs to enable
+ extended TLS configuration for each implementation. For
+ example, configuring the minimum TLS version or supported
+ cipher suites. \n A set of common keys MAY be defined
+ by the API in the future. To avoid any ambiguity, implementation-specific
+ definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`.
+ Un-prefixed names are reserved for key names defined by
+ Gateway API. \n Support: Implementation-specific"
+ maxProperties: 16
+ type: object
+ type: object
+ x-kubernetes-validations:
+ - message: certificateRefs must be specified when TLSModeType
+ is Terminate
+ rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs)
+ > 0 : true'
+ required:
+ - name
+ - port
+ - protocol
+ type: object
+ maxItems: 64
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ x-kubernetes-validations:
+ - message: tls must be specified for protocols ['HTTPS', 'TLS']
+ rule: 'self.all(l, l.protocol in [''HTTPS'', ''TLS''] ? has(l.tls)
+ : true)'
+ - message: tls must not be specified for protocols ['HTTP', 'TCP',
+ 'UDP']
+ rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ?
+ !has(l.tls) : true)'
+ - message: hostname must not be specified for protocols ['TCP', 'UDP']
+ rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname)
+ || l.hostname == '''') : true)'
+ - message: Listener name must be unique within the Gateway
+ rule: self.all(l1, self.exists_one(l2, l1.name == l2.name))
+ - message: Combination of port, protocol and hostname must be unique
+ for each listener
+ rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol
+ == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname
+ == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))'
+ required:
+ - gatewayClassName
+ - listeners
+ type: object
+ status:
+ default:
+ conditions:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Accepted
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Programmed
+ description: Status defines the current state of Gateway.
+ properties:
+ addresses:
+ description: "Addresses lists the network addresses that have been
+ bound to the Gateway. \n This list may differ from the addresses
+ provided in the spec under some conditions: \n * no addresses are
+ specified, all addresses are dynamically assigned * a combination
+ of specified and dynamic addresses are assigned * a specified address
+ was unusable (e.g. already in use) \n "
+ items:
+ description: GatewayStatusAddress describes a network address that
+ is bound to a Gateway.
+ oneOf:
+ - properties:
+ type:
+ enum:
+ - IPAddress
+ value:
+ anyOf:
+ - format: ipv4
+ - format: ipv6
+ - properties:
+ type:
+ not:
+ enum:
+ - IPAddress
+ properties:
+ type:
+ default: IPAddress
+ description: Type of the address.
+ maxLength: 253
+ minLength: 1
+ pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ value:
+ description: "Value of the address. The validity of the values
+ will depend on the type and support by the controller. \n
+ Examples: `1.2.3.4`, `128::1`, `my-ip-address`."
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - value
+ type: object
+ x-kubernetes-validations:
+ - message: Hostname value must only contain valid characters (matching
+ ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)
+ rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""):
+ true'
+ maxItems: 16
+ type: array
+ conditions:
+ default:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Accepted
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Programmed
+ description: "Conditions describe the current conditions of the Gateway.
+ \n Implementations should prefer to express Gateway conditions using
+ the `GatewayConditionType` and `GatewayConditionReason` constants
+ so that operators and tools can converge on a common vocabulary
+ to describe Gateway state. \n Known condition types are: \n * \"Accepted\"
+ * \"Programmed\" * \"Ready\""
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended for direct
+ use as an array at the field path .status.conditions. For example,
+ \n type FooStatus struct{ // Represents the observations of a
+ foo's current state. // Known .status.conditions.type are: \"Available\",
+ \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should be when
+ the underlying condition changed. If that is not known, then
+ using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance, if .metadata.generation
+ is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating
+ the reason for the condition's last transition. Producers
+ of specific condition types may define expected values and
+ meanings for this field, and whether the values are considered
+ a guaranteed API. The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across resources
+ like Available, but because arbitrary conditions can be useful
+ (see .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ listeners:
+ description: Listeners provide status for each unique listener port
+ defined in the Spec.
+ items:
+ description: ListenerStatus is the status associated with a Listener.
+ properties:
+ attachedRoutes:
+ description: "AttachedRoutes represents the total number of
+ Routes that have been successfully attached to this Listener.
+ \n Successful attachment of a Route to a Listener is based
+ solely on the combination of the AllowedRoutes field on the
+ corresponding Listener and the Route's ParentRefs field. A
+ Route is successfully attached to a Listener when it is selected
+ by the Listener's AllowedRoutes field AND the Route has a
+ valid ParentRef selecting the whole Gateway resource or a
+ specific Listener as a parent resource (more detail on attachment
+ semantics can be found in the documentation on the various
+ Route kinds ParentRefs fields). Listener or Route status does
+ not impact successful attachment, i.e. the AttachedRoutes
+ field count MUST be set for Listeners with condition Accepted:
+ false and MUST count successfully attached Routes that may
+ themselves have Accepted: false conditions. \n Uses for this
+ field include troubleshooting Route attachment and measuring
+ blast radius/impact of changes to a Listener."
+ format: int32
+ type: integer
+ conditions:
+ description: Conditions describe the current condition of this
+ listener.
+ items:
+ description: "Condition contains details for one aspect of
+ the current state of this API Resource. --- This struct
+ is intended for direct use as an array at the field path
+ .status.conditions. For example, \n type FooStatus struct{
+ // Represents the observations of a foo's current state.
+ // Known .status.conditions.type are: \"Available\", \"Progressing\",
+ and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields
+ }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should
+ be when the underlying condition changed. If that is
+ not known, then using the time when the API field changed
+ is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance,
+ if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the
+ current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier
+ indicating the reason for the condition's last transition.
+ Producers of specific condition types may define expected
+ values and meanings for this field, and whether the
+ values are considered a guaranteed API. The value should
+ be a CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False,
+ Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across
+ resources like Available, but because arbitrary conditions
+ can be useful (see .node.status.conditions), the ability
+ to deconflict is important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ name:
+ description: Name is the name of the Listener that this status
+ corresponds to.
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ supportedKinds:
+ description: "SupportedKinds is the list indicating the Kinds
+ supported by this listener. This MUST represent the kinds
+ an implementation supports for that Listener configuration.
+ \n If kinds are specified in Spec that are not supported,
+ they MUST NOT appear in this list and an implementation MUST
+ set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\"
+ reason. If both valid and invalid Route kinds are specified,
+ the implementation MUST reference the valid Route kinds that
+ have been specified."
+ items:
+ description: RouteGroupKind indicates the group and kind of
+ a Route resource.
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: Group is the group of the Route.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is the kind of the Route.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ required:
+ - kind
+ type: object
+ maxItems: 8
+ type: array
+ required:
+ - attachedRoutes
+ - conditions
+ - name
+ - supportedKinds
+ type: object
+ maxItems: 64
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
+ - additionalPrinterColumns:
+ - jsonPath: .spec.gatewayClassName
+ name: Class
+ type: string
+ - jsonPath: .status.addresses[*].value
+ name: Address
+ type: string
+ - jsonPath: .status.conditions[?(@.type=="Programmed")].status
+ name: Programmed
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: Gateway represents an instance of a service-traffic handling
+ infrastructure by binding Listeners to a set of IP addresses.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of Gateway.
+ properties:
+ addresses:
+ description: "Addresses requested for this Gateway. This is optional
+ and behavior can depend on the implementation. If a value is set
+ in the spec and the requested address is invalid or unavailable,
+ the implementation MUST indicate this in the associated entry in
+ GatewayStatus.Addresses. \n The Addresses field represents a request
+ for the address(es) on the \"outside of the Gateway\", that traffic
+ bound for this Gateway will use. This could be the IP address or
+ hostname of an external load balancer or other networking infrastructure,
+ or some other address that traffic will be sent to. \n If no Addresses
+ are specified, the implementation MAY schedule the Gateway in an
+ implementation-specific manner, assigning an appropriate set of
+ Addresses. \n The implementation MUST bind all Listeners to every
+ GatewayAddress that it assigns to the Gateway and add a corresponding
+ entry in GatewayStatus.Addresses. \n Support: Extended \n "
+ items:
+ description: GatewayAddress describes an address that can be bound
+ to a Gateway.
+ oneOf:
+ - properties:
+ type:
+ enum:
+ - IPAddress
+ value:
+ anyOf:
+ - format: ipv4
+ - format: ipv6
+ - properties:
+ type:
+ not:
+ enum:
+ - IPAddress
+ properties:
+ type:
+ default: IPAddress
+ description: Type of the address.
+ maxLength: 253
+ minLength: 1
+ pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ value:
+ description: "Value of the address. The validity of the values
+ will depend on the type and support by the controller. \n
+ Examples: `1.2.3.4`, `128::1`, `my-ip-address`."
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - value
+ type: object
+ x-kubernetes-validations:
+ - message: Hostname value must only contain valid characters (matching
+ ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)
+ rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""):
+ true'
+ maxItems: 16
+ type: array
+ x-kubernetes-validations:
+ - message: IPAddress values must be unique
+ rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2,
+ a2.type == a1.type && a2.value == a1.value) : true )'
+ - message: Hostname values must be unique
+ rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2,
+ a2.type == a1.type && a2.value == a1.value) : true )'
+ gatewayClassName:
+ description: GatewayClassName used for this Gateway. This is the name
+ of a GatewayClass resource.
+ maxLength: 253
+ minLength: 1
+ type: string
+ listeners:
+ description: "Listeners associated with this Gateway. Listeners define
+ logical endpoints that are bound on this Gateway's addresses. At
+ least one Listener MUST be specified. \n Each Listener in a set
+ of Listeners (for example, in a single Gateway) MUST be _distinct_,
+ in that a traffic flow MUST be able to be assigned to exactly one
+ listener. (This section uses \"set of Listeners\" rather than \"Listeners
+ in a single Gateway\" because implementations MAY merge configuration
+ from multiple Gateways onto a single data plane, and these rules
+ _also_ apply in that case). \n Practically, this means that each
+ listener in a set MUST have a unique combination of Port, Protocol,
+ and, if supported by the protocol, Hostname. \n Some combinations
+ of port, protocol, and TLS settings are considered Core support
+ and MUST be supported by implementations based on their targeted
+ conformance profile: \n HTTP Profile \n 1. HTTPRoute, Port: 80,
+ Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode:
+ Terminate, TLS keypair provided \n TLS Profile \n 1. TLSRoute, Port:
+ 443, Protocol: TLS, TLS Mode: Passthrough \n \"Distinct\" Listeners
+ have the following property: \n The implementation can match inbound
+ requests to a single distinct Listener. When multiple Listeners
+ share values for fields (for example, two Listeners with the same
+ Port value), the implementation can match requests to only one of
+ the Listeners using other Listener fields. \n For example, the following
+ Listener scenarios are distinct: \n 1. Multiple Listeners with the
+ same Port that all use the \"HTTP\" Protocol that all have unique
+ Hostname values. 2. Multiple Listeners with the same Port that use
+ either the \"HTTPS\" or \"TLS\" Protocol that all have unique Hostname
+ values. 3. A mixture of \"TCP\" and \"UDP\" Protocol Listeners,
+ where no Listener with the same Protocol has the same Port value.
+ \n Some fields in the Listener struct have possible values that
+ affect whether the Listener is distinct. Hostname is particularly
+ relevant for HTTP or HTTPS protocols. \n When using the Hostname
+ value to select between same-Port, same-Protocol Listeners, the
+ Hostname value must be different on each Listener for the Listener
+ to be distinct. \n When the Listeners are distinct based on Hostname,
+ inbound request hostnames MUST match from the most specific to least
+ specific Hostname values to choose the correct Listener and its
+ associated set of Routes. \n Exact matches must be processed before
+ wildcard matches, and wildcard matches must be processed before
+ fallback (empty Hostname value) matches. For example, `\"foo.example.com\"`
+ takes precedence over `\"*.example.com\"`, and `\"*.example.com\"`
+ takes precedence over `\"\"`. \n Additionally, if there are multiple
+ wildcard entries, more specific wildcard entries must be processed
+ before less specific wildcard entries. For example, `\"*.foo.example.com\"`
+ takes precedence over `\"*.example.com\"`. The precise definition
+ here is that the higher the number of dots in the hostname to the
+ right of the wildcard character, the higher the precedence. \n The
+ wildcard character will match any number of characters _and dots_
+ to the left, however, so `\"*.example.com\"` will match both `\"foo.bar.example.com\"`
+ _and_ `\"bar.example.com\"`. \n If a set of Listeners contains Listeners
+ that are not distinct, then those Listeners are Conflicted, and
+ the implementation MUST set the \"Conflicted\" condition in the
+ Listener Status to \"True\". \n Implementations MAY choose to accept
+ a Gateway with some Conflicted Listeners only if they only accept
+ the partial Listener set that contains no Conflicted Listeners.
+ To put this another way, implementations may accept a partial Listener
+ set only if they throw out *all* the conflicting Listeners. No picking
+ one of the conflicting listeners as the winner. This also means
+ that the Gateway must have at least one non-conflicting Listener
+ in this case, otherwise it violates the requirement that at least
+ one Listener must be present. \n The implementation MUST set a \"ListenersNotValid\"
+ condition on the Gateway Status when the Gateway contains Conflicted
+ Listeners whether or not they accept the Gateway. That Condition
+ SHOULD clearly indicate in the Message which Listeners are conflicted,
+ and which are Accepted. Additionally, the Listener status for those
+ listeners SHOULD indicate which Listeners are conflicted and not
+ Accepted. \n A Gateway's Listeners are considered \"compatible\"
+ if: \n 1. They are distinct. 2. The implementation can serve them
+ in compliance with the Addresses requirement that all Listeners
+ are available on all assigned addresses. \n Compatible combinations
+ in Extended support are expected to vary across implementations.
+ A combination that is compatible for one implementation may not
+ be compatible for another. \n For example, an implementation that
+ cannot serve both TCP and UDP listeners on the same address, or
+ cannot mix HTTPS and generic TLS listens on the same port would
+ not consider those cases compatible, even though they are distinct.
+ \n Note that requests SHOULD match at most one Listener. For example,
+ if Listeners are defined for \"foo.example.com\" and \"*.example.com\",
+ a request to \"foo.example.com\" SHOULD only be routed using routes
+ attached to the \"foo.example.com\" Listener (and not the \"*.example.com\"
+ Listener). This concept is known as \"Listener Isolation\". Implementations
+ that do not support Listener Isolation MUST clearly document this.
+ \n Implementations MAY merge separate Gateways onto a single set
+ of Addresses if all Listeners across all Gateways are compatible.
+ \n Support: Core"
+ items:
+ description: Listener embodies the concept of a logical endpoint
+ where a Gateway accepts network connections.
+ properties:
+ allowedRoutes:
+ default:
+ namespaces:
+ from: Same
+ description: "AllowedRoutes defines the types of routes that
+ MAY be attached to a Listener and the trusted namespaces where
+ those Route resources MAY be present. \n Although a client
+ request may match multiple route rules, only one rule may
+ ultimately receive the request. Matching precedence MUST be
+ determined in order of the following criteria: \n * The most
+ specific match as defined by the Route type. * The oldest
+ Route based on creation timestamp. For example, a Route with
+ a creation timestamp of \"2020-09-08 01:02:03\" is given precedence
+ over a Route with a creation timestamp of \"2020-09-08 01:02:04\".
+ * If everything else is equivalent, the Route appearing first
+ in alphabetical order (namespace/name) should be given precedence.
+ For example, foo/bar is given precedence over foo/baz. \n
+ All valid rules within a Route attached to this Listener should
+ be implemented. Invalid Route rules can be ignored (sometimes
+ that will mean the full Route). If a Route rule transitions
+ from valid to invalid, support for that Route rule should
+ be dropped to ensure consistency. For example, even if a filter
+ specified by a Route rule is invalid, the rest of the rules
+ within that Route should still be supported. \n Support: Core"
+ properties:
+ kinds:
+ description: "Kinds specifies the groups and kinds of Routes
+ that are allowed to bind to this Gateway Listener. When
+ unspecified or empty, the kinds of Routes selected are
+ determined using the Listener protocol. \n A RouteGroupKind
+ MUST correspond to kinds of Routes that are compatible
+ with the application protocol specified in the Listener's
+ Protocol field. If an implementation does not support
+ or recognize this resource type, it MUST set the \"ResolvedRefs\"
+ condition to False for this Listener with the \"InvalidRouteKinds\"
+ reason. \n Support: Core"
+ items:
+ description: RouteGroupKind indicates the group and kind
+ of a Route resource.
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: Group is the group of the Route.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is the kind of the Route.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ required:
+ - kind
+ type: object
+ maxItems: 8
+ type: array
+ namespaces:
+ default:
+ from: Same
+ description: "Namespaces indicates namespaces from which
+ Routes may be attached to this Listener. This is restricted
+ to the namespace of this Gateway by default. \n Support:
+ Core"
+ properties:
+ from:
+ default: Same
+ description: "From indicates where Routes will be selected
+ for this Gateway. Possible values are: \n * All: Routes
+ in all namespaces may be used by this Gateway. * Selector:
+ Routes in namespaces selected by the selector may
+ be used by this Gateway. * Same: Only Routes in the
+ same namespace may be used by this Gateway. \n Support:
+ Core"
+ enum:
+ - All
+ - Selector
+ - Same
+ type: string
+ selector:
+ description: "Selector must be specified when From is
+ set to \"Selector\". In that case, only Routes in
+ Namespaces matching this Selector will be selected
+ by this Gateway. This field is ignored for other values
+ of \"From\". \n Support: Core"
+ properties:
+ matchExpressions:
+ description: matchExpressions is a list of label
+ selector requirements. The requirements are ANDed.
+ items:
+ description: A label selector requirement is a
+ selector that contains values, a key, and an
+ operator that relates the key and values.
+ properties:
+ key:
+ description: key is the label key that the
+ selector applies to.
+ type: string
+ operator:
+ description: operator represents a key's relationship
+ to a set of values. Valid operators are
+ In, NotIn, Exists and DoesNotExist.
+ type: string
+ values:
+ description: values is an array of string
+ values. If the operator is In or NotIn,
+ the values array must be non-empty. If the
+ operator is Exists or DoesNotExist, the
+ values array must be empty. This array is
+ replaced during a strategic merge patch.
+ items:
+ type: string
+ type: array
+ required:
+ - key
+ - operator
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ description: matchLabels is a map of {key,value}
+ pairs. A single {key,value} in the matchLabels
+ map is equivalent to an element of matchExpressions,
+ whose key field is "key", the operator is "In",
+ and the values array contains only "value". The
+ requirements are ANDed.
+ type: object
+ type: object
+ x-kubernetes-map-type: atomic
+ type: object
+ type: object
+ hostname:
+ description: "Hostname specifies the virtual hostname to match
+ for protocol types that define this concept. When unspecified,
+ all hostnames are matched. This field is ignored for protocols
+ that don't require hostname based matching. \n Implementations
+ MUST apply Hostname matching appropriately for each of the
+ following protocols: \n * TLS: The Listener Hostname MUST
+ match the SNI. * HTTP: The Listener Hostname MUST match the
+ Host header of the request. * HTTPS: The Listener Hostname
+ SHOULD match at both the TLS and HTTP protocol layers as described
+ above. If an implementation does not ensure that both the
+ SNI and Host header match the Listener hostname, it MUST clearly
+ document that. \n For HTTPRoute and TLSRoute resources, there
+ is an interaction with the `spec.hostnames` array. When both
+ listener and route specify hostnames, there MUST be an intersection
+ between the values for a Route to be accepted. For more information,
+ refer to the Route specific Hostnames documentation. \n Hostnames
+ that are prefixed with a wildcard label (`*.`) are interpreted
+ as a suffix match. That means that a match for `*.example.com`
+ would match both `test.example.com`, and `foo.test.example.com`,
+ but not `example.com`. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ name:
+ description: "Name is the name of the Listener. This name MUST
+ be unique within a Gateway. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ port:
+ description: "Port is the network port. Multiple listeners may
+ use the same port, subject to the Listener compatibility rules.
+ \n Support: Core"
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ protocol:
+ description: "Protocol specifies the network protocol this listener
+ expects to receive. \n Support: Core"
+ maxLength: 255
+ minLength: 1
+ pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$
+ type: string
+ tls:
+ description: "TLS is the TLS configuration for the Listener.
+ This field is required if the Protocol field is \"HTTPS\"
+ or \"TLS\". It is invalid to set this field if the Protocol
+ field is \"HTTP\", \"TCP\", or \"UDP\". \n The association
+ of SNIs to Certificate defined in GatewayTLSConfig is defined
+ based on the Hostname field for this listener. \n The GatewayClass
+ MUST use the longest matching SNI out of all available certificates
+ for any TLS handshake. \n Support: Core"
+ properties:
+ certificateRefs:
+ description: "CertificateRefs contains a series of references
+ to Kubernetes objects that contains TLS certificates and
+ private keys. These certificates are used to establish
+ a TLS handshake for requests that match the hostname of
+ the associated listener. \n A single CertificateRef to
+ a Kubernetes Secret has \"Core\" support. Implementations
+ MAY choose to support attaching multiple certificates
+ to a Listener, but this behavior is implementation-specific.
+ \n References to a resource in different namespace are
+ invalid UNLESS there is a ReferenceGrant in the target
+ namespace that allows the certificate to be attached.
+ If a ReferenceGrant does not allow this reference, the
+ \"ResolvedRefs\" condition MUST be set to False for this
+ listener with the \"RefNotPermitted\" reason. \n This
+ field is required to have at least one element when the
+ mode is set to \"Terminate\" (default) and is optional
+ otherwise. \n CertificateRefs can reference to standard
+ Kubernetes resources, i.e. Secret, or implementation-specific
+ custom resources. \n Support: Core - A single reference
+ to a Kubernetes Secret of type kubernetes.io/tls \n Support:
+ Implementation-specific (More than one reference or other
+ resource types)"
+ items:
+ description: "SecretObjectReference identifies an API
+ object including its namespace, defaulting to Secret.
+ \n The API object must be valid in the cluster; the
+ Group and Kind must be registered in the cluster for
+ this reference to be valid. \n References to objects
+ with invalid Group and Kind are not valid, and must
+ be rejected by the implementation, with appropriate
+ Conditions set on the containing object."
+ properties:
+ group:
+ default: ""
+ description: Group is the group of the referent. For
+ example, "gateway.networking.k8s.io". When unspecified
+ or empty string, core API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Secret
+ description: Kind is kind of the referent. For example
+ "Secret".
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referenced
+ object. When unspecified, the local namespace is
+ inferred. \n Note that when a namespace different
+ than the local namespace is specified, a ReferenceGrant
+ object is required in the referent namespace to
+ allow that namespace's owner to accept the reference.
+ See the ReferenceGrant documentation for details.
+ \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ required:
+ - name
+ type: object
+ maxItems: 64
+ type: array
+ mode:
+ default: Terminate
+ description: "Mode defines the TLS behavior for the TLS
+ session initiated by the client. There are two possible
+ modes: \n - Terminate: The TLS session between the downstream
+ client and the Gateway is terminated at the Gateway. This
+ mode requires certificateRefs to be set and contain at
+ least one element. - Passthrough: The TLS session is NOT
+ terminated by the Gateway. This implies that the Gateway
+ can't decipher the TLS stream except for the ClientHello
+ message of the TLS protocol. CertificateRefs field is
+ ignored in this mode. \n Support: Core"
+ enum:
+ - Terminate
+ - Passthrough
+ type: string
+ options:
+ additionalProperties:
+ description: AnnotationValue is the value of an annotation
+ in Gateway API. This is used for validation of maps
+ such as TLS options. This roughly matches Kubernetes
+ annotation validation, although the length validation
+ in that case is based on the entire size of the annotations
+ struct.
+ maxLength: 4096
+ minLength: 0
+ type: string
+ description: "Options are a list of key/value pairs to enable
+ extended TLS configuration for each implementation. For
+ example, configuring the minimum TLS version or supported
+ cipher suites. \n A set of common keys MAY be defined
+ by the API in the future. To avoid any ambiguity, implementation-specific
+ definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`.
+ Un-prefixed names are reserved for key names defined by
+ Gateway API. \n Support: Implementation-specific"
+ maxProperties: 16
+ type: object
+ type: object
+ x-kubernetes-validations:
+ - message: certificateRefs must be specified when TLSModeType
+ is Terminate
+ rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs)
+ > 0 : true'
+ required:
+ - name
+ - port
+ - protocol
+ type: object
+ maxItems: 64
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ x-kubernetes-validations:
+ - message: tls must be specified for protocols ['HTTPS', 'TLS']
+ rule: 'self.all(l, l.protocol in [''HTTPS'', ''TLS''] ? has(l.tls)
+ : true)'
+ - message: tls must not be specified for protocols ['HTTP', 'TCP',
+ 'UDP']
+ rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ?
+ !has(l.tls) : true)'
+ - message: hostname must not be specified for protocols ['TCP', 'UDP']
+ rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname)
+ || l.hostname == '''') : true)'
+ - message: Listener name must be unique within the Gateway
+ rule: self.all(l1, self.exists_one(l2, l1.name == l2.name))
+ - message: Combination of port, protocol and hostname must be unique
+ for each listener
+ rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol
+ == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname
+ == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))'
+ required:
+ - gatewayClassName
+ - listeners
+ type: object
+ status:
+ default:
+ conditions:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Accepted
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Programmed
+ description: Status defines the current state of Gateway.
+ properties:
+ addresses:
+ description: "Addresses lists the network addresses that have been
+ bound to the Gateway. \n This list may differ from the addresses
+ provided in the spec under some conditions: \n * no addresses are
+ specified, all addresses are dynamically assigned * a combination
+ of specified and dynamic addresses are assigned * a specified address
+ was unusable (e.g. already in use) \n "
+ items:
+ description: GatewayStatusAddress describes a network address that
+ is bound to a Gateway.
+ oneOf:
+ - properties:
+ type:
+ enum:
+ - IPAddress
+ value:
+ anyOf:
+ - format: ipv4
+ - format: ipv6
+ - properties:
+ type:
+ not:
+ enum:
+ - IPAddress
+ properties:
+ type:
+ default: IPAddress
+ description: Type of the address.
+ maxLength: 253
+ minLength: 1
+ pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ value:
+ description: "Value of the address. The validity of the values
+ will depend on the type and support by the controller. \n
+ Examples: `1.2.3.4`, `128::1`, `my-ip-address`."
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - value
+ type: object
+ x-kubernetes-validations:
+ - message: Hostname value must only contain valid characters (matching
+ ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$)
+ rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""):
+ true'
+ maxItems: 16
+ type: array
+ conditions:
+ default:
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Accepted
+ - lastTransitionTime: "1970-01-01T00:00:00Z"
+ message: Waiting for controller
+ reason: Pending
+ status: Unknown
+ type: Programmed
+ description: "Conditions describe the current conditions of the Gateway.
+ \n Implementations should prefer to express Gateway conditions using
+ the `GatewayConditionType` and `GatewayConditionReason` constants
+ so that operators and tools can converge on a common vocabulary
+ to describe Gateway state. \n Known condition types are: \n * \"Accepted\"
+ * \"Programmed\" * \"Ready\""
+ items:
+ description: "Condition contains details for one aspect of the current
+ state of this API Resource. --- This struct is intended for direct
+ use as an array at the field path .status.conditions. For example,
+ \n type FooStatus struct{ // Represents the observations of a
+ foo's current state. // Known .status.conditions.type are: \"Available\",
+ \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should be when
+ the underlying condition changed. If that is not known, then
+ using the time when the API field changed is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance, if .metadata.generation
+ is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the current
+ state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier indicating
+ the reason for the condition's last transition. Producers
+ of specific condition types may define expected values and
+ meanings for this field, and whether the values are considered
+ a guaranteed API. The value should be a CamelCase string.
+ This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False, Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across resources
+ like Available, but because arbitrary conditions can be useful
+ (see .node.status.conditions), the ability to deconflict is
+ important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ listeners:
+ description: Listeners provide status for each unique listener port
+ defined in the Spec.
+ items:
+ description: ListenerStatus is the status associated with a Listener.
+ properties:
+ attachedRoutes:
+ description: "AttachedRoutes represents the total number of
+ Routes that have been successfully attached to this Listener.
+ \n Successful attachment of a Route to a Listener is based
+ solely on the combination of the AllowedRoutes field on the
+ corresponding Listener and the Route's ParentRefs field. A
+ Route is successfully attached to a Listener when it is selected
+ by the Listener's AllowedRoutes field AND the Route has a
+ valid ParentRef selecting the whole Gateway resource or a
+ specific Listener as a parent resource (more detail on attachment
+ semantics can be found in the documentation on the various
+ Route kinds ParentRefs fields). Listener or Route status does
+ not impact successful attachment, i.e. the AttachedRoutes
+ field count MUST be set for Listeners with condition Accepted:
+ false and MUST count successfully attached Routes that may
+ themselves have Accepted: false conditions. \n Uses for this
+ field include troubleshooting Route attachment and measuring
+ blast radius/impact of changes to a Listener."
+ format: int32
+ type: integer
+ conditions:
+ description: Conditions describe the current condition of this
+ listener.
+ items:
+ description: "Condition contains details for one aspect of
+ the current state of this API Resource. --- This struct
+ is intended for direct use as an array at the field path
+ .status.conditions. For example, \n type FooStatus struct{
+ // Represents the observations of a foo's current state.
+ // Known .status.conditions.type are: \"Available\", \"Progressing\",
+ and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields
+ }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should
+ be when the underlying condition changed. If that is
+ not known, then using the time when the API field changed
+ is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance,
+ if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the
+ current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier
+ indicating the reason for the condition's last transition.
+ Producers of specific condition types may define expected
+ values and meanings for this field, and whether the
+ values are considered a guaranteed API. The value should
+ be a CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False,
+ Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across
+ resources like Available, but because arbitrary conditions
+ can be useful (see .node.status.conditions), the ability
+ to deconflict is important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ name:
+ description: Name is the name of the Listener that this status
+ corresponds to.
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ supportedKinds:
+ description: "SupportedKinds is the list indicating the Kinds
+ supported by this listener. This MUST represent the kinds
+ an implementation supports for that Listener configuration.
+ \n If kinds are specified in Spec that are not supported,
+ they MUST NOT appear in this list and an implementation MUST
+ set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\"
+ reason. If both valid and invalid Route kinds are specified,
+ the implementation MUST reference the valid Route kinds that
+ have been specified."
+ items:
+ description: RouteGroupKind indicates the group and kind of
+ a Route resource.
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: Group is the group of the Route.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is the kind of the Route.
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ required:
+ - kind
+ type: object
+ maxItems: 8
+ type: array
+ required:
+ - attachedRoutes
+ - conditions
+ - name
+ - supportedKinds
+ type: object
+ maxItems: 64
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+status:
+ acceptedNames:
+ kind: ""
+ plural: ""
+ conditions: null
+ storedVersions: null
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466
+ gateway.networking.k8s.io/bundle-version: v1.0.0
+ gateway.networking.k8s.io/channel: standard
+ creationTimestamp: null
+ name: httproutes.gateway.networking.k8s.io
+spec:
+ group: gateway.networking.k8s.io
+ names:
+ categories:
+ - gateway-api
+ kind: HTTPRoute
+ listKind: HTTPRouteList
+ plural: httproutes
+ singular: httproute
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .spec.hostnames
+ name: Hostnames
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1
+ schema:
+ openAPIV3Schema:
+ description: HTTPRoute provides a way to route HTTP requests. This includes
+ the capability to match requests by hostname, path, header, or query param.
+ Filters can be used to specify additional processing steps. Backends specify
+ where matching requests should be routed.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of HTTPRoute.
+ properties:
+ hostnames:
+ description: "Hostnames defines a set of hostnames that should match
+ against the HTTP Host header to select a HTTPRoute used to process
+ the request. Implementations MUST ignore any port value specified
+ in the HTTP Host header while performing a match and (absent of
+ any applicable header modification configuration) MUST forward this
+ header unmodified to the backend. \n Valid values for Hostnames
+ are determined by RFC 1123 definition of a hostname with 2 notable
+ exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed
+ with a wildcard label (`*.`). The wildcard label must appear by
+ itself as the first label. \n If a hostname is specified by both
+ the Listener and HTTPRoute, there must be at least one intersecting
+ hostname for the HTTPRoute to be attached to the Listener. For example:
+ \n * A Listener with `test.example.com` as the hostname matches
+ HTTPRoutes that have either not specified any hostnames, or have
+ specified at least one of `test.example.com` or `*.example.com`.
+ * A Listener with `*.example.com` as the hostname matches HTTPRoutes
+ that have either not specified any hostnames or have specified at
+ least one hostname that matches the Listener hostname. For example,
+ `*.example.com`, `test.example.com`, and `foo.test.example.com`
+ would all match. On the other hand, `example.com` and `test.example.net`
+ would not match. \n Hostnames that are prefixed with a wildcard
+ label (`*.`) are interpreted as a suffix match. That means that
+ a match for `*.example.com` would match both `test.example.com`,
+ and `foo.test.example.com`, but not `example.com`. \n If both the
+ Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames
+ that do not match the Listener hostname MUST be ignored. For example,
+ if a Listener specified `*.example.com`, and the HTTPRoute specified
+ `test.example.com` and `test.example.net`, `test.example.net` must
+ not be considered for a match. \n If both the Listener and HTTPRoute
+ have specified hostnames, and none match with the criteria above,
+ then the HTTPRoute is not accepted. The implementation must raise
+ an 'Accepted' Condition with a status of `False` in the corresponding
+ RouteParentStatus. \n In the event that multiple HTTPRoutes specify
+ intersecting hostnames (e.g. overlapping wildcard matching and exact
+ matching hostnames), precedence must be given to rules from the
+ HTTPRoute with the largest number of: \n * Characters in a matching
+ non-wildcard hostname. * Characters in a matching hostname. \n If
+ ties exist across multiple Routes, the matching precedence rules
+ for HTTPRouteMatches takes over. \n Support: Core"
+ items:
+ description: "Hostname is the fully qualified domain name of a network
+ host. This matches the RFC 1123 definition of a hostname with
+ 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname
+ may be prefixed with a wildcard label (`*.`). The wildcard label
+ must appear by itself as the first label. \n Hostname can be \"precise\"
+ which is a domain name without the terminating dot of a network
+ host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain
+ name prefixed with a single wildcard label (e.g. `*.example.com`).
+ \n Note that as per RFC1035 and RFC1123, a *label* must consist
+ of lower case alphanumeric characters or '-', and must start and
+ end with an alphanumeric character. No other punctuation is allowed."
+ maxLength: 253
+ minLength: 1
+ pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ maxItems: 16
+ type: array
+ parentRefs:
+ description: "ParentRefs references the resources (usually Gateways)
+ that a Route wants to be attached to. Note that the referenced parent
+ resource needs to allow this for the attachment to be complete.
+ For Gateways, that means the Gateway needs to allow attachment from
+ Routes of this kind and namespace. For Services, that means the
+ Service must either be in the same namespace for a \"producer\"
+ route, or the mesh implementation must support and allow \"consumer\"
+ routes for the referenced Service. ReferenceGrant is not applicable
+ for governing ParentRefs to Services - it is not possible to create
+ a \"producer\" route for a Service in a different namespace from
+ the Route. \n There are two kinds of parent resources with \"Core\"
+ support: \n * Gateway (Gateway conformance profile) This API may
+ be extended in the future to support additional kinds of parent
+ resources. \n ParentRefs must be _distinct_. This means either that:
+ \n * They select different objects. If this is the case, then parentRef
+ entries are distinct. In terms of fields, this means that the multi-part
+ key defined by `group`, `kind`, `namespace`, and `name` must be
+ unique across all parentRef entries in the Route. * They do not
+ select different objects, but for each optional field used, each
+ ParentRef that selects the same object must set the same set of
+ optional fields to different values. If one ParentRef sets a combination
+ of optional fields, all must set the same combination. \n Some examples:
+ \n * If one ParentRef sets `sectionName`, all ParentRefs referencing
+ the same object must also set `sectionName`. * If one ParentRef
+ sets `port`, all ParentRefs referencing the same object must also
+ set `port`. * If one ParentRef sets `sectionName` and `port`, all
+ ParentRefs referencing the same object must also set `sectionName`
+ and `port`. \n It is possible to separately reference multiple distinct
+ objects that may be collapsed by an implementation. For example,
+ some implementations may choose to merge compatible Gateway Listeners
+ together. If that is the case, the list of routes attached to those
+ resources should also be merged. \n Note that for ParentRefs that
+ cross namespace boundaries, there are specific rules. Cross-namespace
+ references are only valid if they are explicitly allowed by something
+ in the namespace they are referring to. For example, Gateway has
+ the AllowedRoutes field, and ReferenceGrant provides a generic way
+ to enable other kinds of cross-namespace reference. \n \n "
+ items:
+ description: "ParentReference identifies an API object (usually
+ a Gateway) that can be considered a parent of this resource (usually
+ a route). There are two kinds of parent resources with \"Core\"
+ support: \n * Gateway (Gateway conformance profile) * Service
+ (Mesh conformance profile, experimental, ClusterIP Services only)
+ \n This API may be extended in the future to support additional
+ kinds of parent resources. \n The API object must be valid in
+ the cluster; the Group and Kind must be registered in the cluster
+ for this reference to be valid."
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: "Group is the group of the referent. When unspecified,
+ \"gateway.networking.k8s.io\" is inferred. To set the core
+ API group (such as for a \"Service\" kind referent), Group
+ must be explicitly set to \"\" (empty string). \n Support:
+ Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Gateway
+ description: "Kind is kind of the referent. \n There are two
+ kinds of parent resources with \"Core\" support: \n * Gateway
+ (Gateway conformance profile) * Service (Mesh conformance
+ profile, experimental, ClusterIP Services only) \n Support
+ for other resources is Implementation-Specific."
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: "Name is the name of the referent. \n Support:
+ Core"
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referent. When
+ unspecified, this refers to the local namespace of the Route.
+ \n Note that there are specific rules for ParentRefs which
+ cross namespace boundaries. Cross-namespace references are
+ only valid if they are explicitly allowed by something in
+ the namespace they are referring to. For example: Gateway
+ has the AllowedRoutes field, and ReferenceGrant provides a
+ generic way to enable any other kind of cross-namespace reference.
+ \n \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ sectionName:
+ description: "SectionName is the name of a section within the
+ target resource. In the following resources, SectionName is
+ interpreted as the following: \n * Gateway: Listener Name.
+ When both Port (experimental) and SectionName are specified,
+ the name and port of the selected listener must match both
+ specified values. * Service: Port Name. When both Port (experimental)
+ and SectionName are specified, the name and port of the selected
+ listener must match both specified values. Note that attaching
+ Routes to Services as Parents is part of experimental Mesh
+ support and is not supported for any other purpose. \n Implementations
+ MAY choose to support attaching Routes to other resources.
+ If that is the case, they MUST clearly document how SectionName
+ is interpreted. \n When unspecified (empty string), this will
+ reference the entire resource. For the purpose of status,
+ an attachment is considered successful if at least one section
+ in the parent resource accepts it. For example, Gateway listeners
+ can restrict which Routes can attach to them by Route kind,
+ namespace, or hostname. If 1 of 2 Gateway listeners accept
+ attachment from the referencing Route, the Route MUST be considered
+ successfully attached. If no Gateway listeners accept attachment
+ from this Route, the Route MUST be considered detached from
+ the Gateway. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ required:
+ - name
+ type: object
+ maxItems: 32
+ type: array
+ x-kubernetes-validations:
+ - message: sectionName must be specified when parentRefs includes
+ 2 or more references to the same parent
+ rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind
+ == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__)
+ || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__
+ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) &&
+ p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName)
+ || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName
+ == '''')) : true))'
+ - message: sectionName must be unique when parentRefs includes 2 or
+ more references to the same parent
+ rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind
+ == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__)
+ || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__
+ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) &&
+ p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName)
+ || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName
+ == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName
+ == p2.sectionName))))
+ rules:
+ default:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /
+ description: Rules are a list of HTTP matchers, filters and actions.
+ items:
+ description: HTTPRouteRule defines semantics for matching an HTTP
+ request based on conditions (matches), processing it (filters),
+ and forwarding the request to an API object (backendRefs).
+ properties:
+ backendRefs:
+ description: "BackendRefs defines the backend(s) where matching
+ requests should be sent. \n Failure behavior here depends
+ on how many BackendRefs are specified and how many are invalid.
+ \n If *all* entries in BackendRefs are invalid, and there
+ are also no filters specified in this route rule, *all* traffic
+ which matches this rule MUST receive a 500 status code. \n
+ See the HTTPBackendRef definition for the rules about what
+ makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef
+ is invalid, 500 status codes MUST be returned for requests
+ that would have otherwise been routed to an invalid backend.
+ If multiple backends are specified, and some are invalid,
+ the proportion of requests that would otherwise have been
+ routed to an invalid backend MUST receive a 500 status code.
+ \n For example, if two backends are specified with equal weights,
+ and one is invalid, 50 percent of traffic must receive a 500.
+ Implementations may choose how that 50 percent is determined.
+ \n Support: Core for Kubernetes Service \n Support: Extended
+ for Kubernetes ServiceImport \n Support: Implementation-specific
+ for any other resource \n Support for weight: Core"
+ items:
+ description: "HTTPBackendRef defines how a HTTPRoute forwards
+ a HTTP request. \n Note that when a namespace different
+ than the local namespace is specified, a ReferenceGrant
+ object is required in the referent namespace to allow that
+ namespace's owner to accept the reference. See the ReferenceGrant
+ documentation for details. \n
+ \n When the BackendRef points to a Kubernetes Service, implementations
+ SHOULD honor the appProtocol field if it is set for the
+ target Service Port. \n Implementations supporting appProtocol
+ SHOULD recognize the Kubernetes Standard Application Protocols
+ defined in KEP-3726. \n If a Service appProtocol isn't specified,
+ an implementation MAY infer the backend protocol through
+ its own means. Implementations MAY infer the protocol from
+ the Route type referring to the backend Service. \n If a
+ Route is not able to send traffic to the backend using the
+ specified protocol then the backend is considered invalid.
+ Implementations MUST set the \"ResolvedRefs\" condition
+ to \"False\" with the \"UnsupportedProtocol\" reason. \n
+ "
+ properties:
+ filters:
+ description: "Filters defined at this level should be
+ executed if and only if the request is being forwarded
+ to the backend defined here. \n Support: Implementation-specific
+ (For broader support of filters, use the Filters field
+ in HTTPRouteRule.)"
+ items:
+ description: HTTPRouteFilter defines processing steps
+ that must be completed during the request or response
+ lifecycle. HTTPRouteFilters are meant as an extension
+ point to express processing that may be done in Gateway
+ implementations. Some examples include request or
+ response modification, implementing authentication
+ strategies, rate-limiting, and traffic shaping. API
+ guarantee/conformance is defined based on the type
+ of the filter.
+ properties:
+ extensionRef:
+ description: "ExtensionRef is an optional, implementation-specific
+ extension to the \"filter\" behavior. For example,
+ resource \"myroutefilter\" in group \"networking.example.net\").
+ ExtensionRef MUST NOT be used for core and extended
+ filters. \n This filter can be used multiple times
+ within the same rule. \n Support: Implementation-specific"
+ properties:
+ group:
+ description: Group is the group of the referent.
+ For example, "gateway.networking.k8s.io".
+ When unspecified or empty string, core API
+ group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is kind of the referent. For
+ example "HTTPRoute" or "Service".
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - group
+ - kind
+ - name
+ type: object
+ requestHeaderModifier:
+ description: "RequestHeaderModifier defines a schema
+ for a filter that modifies request headers. \n
+ Support: Core"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It
+ appends to any existing values associated
+ with the header name. \n Input: GET /foo HTTP/1.1
+ my-header: foo \n Config: add: - name: \"my-header\"
+ value: \"bar,baz\" \n Output: GET /foo HTTP/1.1
+ my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from
+ the HTTP request before the action. The value
+ of Remove is a list of HTTP header names.
+ Note that the header names are case-insensitive
+ (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo
+ my-header2: bar my-header3: baz \n Config:
+ remove: [\"my-header1\", \"my-header3\"] \n
+ Output: GET /foo HTTP/1.1 my-header2: bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with
+ the given header (name, value) before the
+ action. \n Input: GET /foo HTTP/1.1 my-header:
+ foo \n Config: set: - name: \"my-header\"
+ value: \"bar\" \n Output: GET /foo HTTP/1.1
+ my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ requestMirror:
+ description: "RequestMirror defines a schema for
+ a filter that mirrors requests. Requests are sent
+ to the specified destination, but responses from
+ that destination are ignored. \n This filter can
+ be used multiple times within the same rule. Note
+ that not all implementations will be able to support
+ mirroring to multiple backends. \n Support: Extended"
+ properties:
+ backendRef:
+ description: "BackendRef references a resource
+ where mirrored requests are sent. \n Mirrored
+ requests must be sent only to a single destination
+ endpoint within this BackendRef, irrespective
+ of how many endpoints are present within this
+ BackendRef. \n If the referent cannot be found,
+ this BackendRef is invalid and must be dropped
+ from the Gateway. The controller must ensure
+ the \"ResolvedRefs\" condition on the Route
+ status is set to `status: False` and not configure
+ this backend in the underlying implementation.
+ \n If there is a cross-namespace reference
+ to an *existing* object that is not allowed
+ by a ReferenceGrant, the controller must ensure
+ the \"ResolvedRefs\" condition on the Route
+ is set to `status: False`, with the \"RefNotPermitted\"
+ reason and not configure this backend in the
+ underlying implementation. \n In either error
+ case, the Message of the `ResolvedRefs` Condition
+ should be used to provide more detail about
+ the problem. \n Support: Extended for Kubernetes
+ Service \n Support: Implementation-specific
+ for any other resource"
+ properties:
+ group:
+ default: ""
+ description: Group is the group of the referent.
+ For example, "gateway.networking.k8s.io".
+ When unspecified or empty string, core
+ API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Service
+ description: "Kind is the Kubernetes resource
+ kind of the referent. For example \"Service\".
+ \n Defaults to \"Service\" when not specified.
+ \n ExternalName services can refer to
+ CNAME DNS records that may live outside
+ of the cluster and as such are difficult
+ to reason about in terms of conformance.
+ They also may not be safe to forward to
+ (see CVE-2021-25740 for more information).
+ Implementations SHOULD NOT support ExternalName
+ Services. \n Support: Core (Services with
+ a type other than ExternalName) \n Support:
+ Implementation-specific (Services with
+ type ExternalName)"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace
+ of the backend. When unspecified, the
+ local namespace is inferred. \n Note that
+ when a namespace different than the local
+ namespace is specified, a ReferenceGrant
+ object is required in the referent namespace
+ to allow that namespace's owner to accept
+ the reference. See the ReferenceGrant
+ documentation for details. \n Support:
+ Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ port:
+ description: Port specifies the destination
+ port number to use for this resource.
+ Port is required when the referent is
+ a Kubernetes Service. In this case, the
+ port number is the service port number,
+ not the target port. For other resources,
+ destination port might be derived from
+ the referent resource or this field.
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ required:
+ - name
+ type: object
+ x-kubernetes-validations:
+ - message: Must have port for Service reference
+ rule: '(size(self.group) == 0 && self.kind
+ == ''Service'') ? has(self.port) : true'
+ required:
+ - backendRef
+ type: object
+ requestRedirect:
+ description: "RequestRedirect defines a schema for
+ a filter that responds to the request with an
+ HTTP redirection. \n Support: Core"
+ properties:
+ hostname:
+ description: "Hostname is the hostname to be
+ used in the value of the `Location` header
+ in the response. When empty, the hostname
+ in the `Host` header of the request is used.
+ \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines parameters used to
+ modify the path of the incoming request. The
+ modified path is then used to construct the
+ `Location` header. When empty, the request
+ path is used as-is. \n Support: Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the
+ value with which to replace the full path
+ of a request during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies
+ the value with which to replace the prefix
+ match of a request during a rewrite or
+ redirect. For example, a request to \"/foo/bar\"
+ with a prefix match of \"/foo\" and a
+ ReplacePrefixMatch of \"/xyz\" would be
+ modified to \"/xyz/bar\". \n Note that
+ this matches the behavior of the PathPrefix
+ match type. This matches full path elements.
+ A path element refers to the list of labels
+ in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored.
+ For example, the paths `/abc`, `/abc/`,
+ and `/abc/def` would all match the prefix
+ `/abc`, but the path `/abcd` would not.
+ \n ReplacePrefixMatch is only compatible
+ with a `PathPrefix` HTTPRouteMatch. Using
+ any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`. \n Request Path
+ | Prefix Match | Replace Prefix | Modified
+ Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo |
+ /xyz/ | /xyz/bar /foo/bar |
+ /foo/ | /xyz | /xyz/bar
+ /foo/bar | /foo/ | /xyz/ |
+ /xyz/bar /foo | /foo |
+ /xyz | /xyz /foo/ | /foo
+ \ | /xyz | /xyz/ /foo/bar
+ \ | /foo | |
+ /bar /foo/ | /foo | | / /foo | /foo |
+ | / /foo/ | /foo
+ \ | / | / /foo |
+ /foo | / | /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path
+ modifier. Additional types may be added
+ in a future release of the API. \n Note
+ that values may be added to this enum,
+ implementations must ensure that unknown
+ values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`, with a Reason
+ of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified
+ when type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ?
+ has(self.replaceFullPath) : true'
+ - message: type must be 'ReplaceFullPath' when
+ replaceFullPath is set
+ rule: 'has(self.replaceFullPath) ? self.type
+ == ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified
+ when type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch''
+ ? has(self.replacePrefixMatch) : true'
+ - message: type must be 'ReplacePrefixMatch'
+ when replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ port:
+ description: "Port is the port to be used in
+ the value of the `Location` header in the
+ response. \n If no port is specified, the
+ redirect port MUST be derived using the following
+ rules: \n * If redirect scheme is not-empty,
+ the redirect port MUST be the well-known port
+ associated with the redirect scheme. Specifically
+ \"http\" to port 80 and \"https\" to port
+ 443. If the redirect scheme does not have
+ a well-known port, the listener port of the
+ Gateway SHOULD be used. * If redirect scheme
+ is empty, the redirect port MUST be the Gateway
+ Listener port. \n Implementations SHOULD NOT
+ add the port number in the 'Location' header
+ in the following cases: \n * A Location header
+ that will use HTTP (whether that is determined
+ via the Listener protocol or the Scheme field)
+ _and_ use port 80. * A Location header that
+ will use HTTPS (whether that is determined
+ via the Listener protocol or the Scheme field)
+ _and_ use port 443. \n Support: Extended"
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ scheme:
+ description: "Scheme is the scheme to be used
+ in the value of the `Location` header in the
+ response. When empty, the scheme of the request
+ is used. \n Scheme redirects can affect the
+ port of the redirect, for more information,
+ refer to the documentation for the port field
+ of this filter. \n Note that values may be
+ added to this enum, implementations must ensure
+ that unknown values will not cause a crash.
+ \n Unknown values here must result in the
+ implementation setting the Accepted Condition
+ for the Route to `status: False`, with a Reason
+ of `UnsupportedValue`. \n Support: Extended"
+ enum:
+ - http
+ - https
+ type: string
+ statusCode:
+ default: 302
+ description: "StatusCode is the HTTP status
+ code to be used in response. \n Note that
+ values may be added to this enum, implementations
+ must ensure that unknown values will not cause
+ a crash. \n Unknown values here must result
+ in the implementation setting the Accepted
+ Condition for the Route to `status: False`,
+ with a Reason of `UnsupportedValue`. \n Support:
+ Core"
+ enum:
+ - 301
+ - 302
+ type: integer
+ type: object
+ responseHeaderModifier:
+ description: "ResponseHeaderModifier defines a schema
+ for a filter that modifies response headers. \n
+ Support: Extended"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It
+ appends to any existing values associated
+ with the header name. \n Input: GET /foo HTTP/1.1
+ my-header: foo \n Config: add: - name: \"my-header\"
+ value: \"bar,baz\" \n Output: GET /foo HTTP/1.1
+ my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from
+ the HTTP request before the action. The value
+ of Remove is a list of HTTP header names.
+ Note that the header names are case-insensitive
+ (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo
+ my-header2: bar my-header3: baz \n Config:
+ remove: [\"my-header1\", \"my-header3\"] \n
+ Output: GET /foo HTTP/1.1 my-header2: bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with
+ the given header (name, value) before the
+ action. \n Input: GET /foo HTTP/1.1 my-header:
+ foo \n Config: set: - name: \"my-header\"
+ value: \"bar\" \n Output: GET /foo HTTP/1.1
+ my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ type:
+ description: "Type identifies the type of filter
+ to apply. As with other API fields, types are
+ classified into three conformance levels: \n -
+ Core: Filter types and their corresponding configuration
+ defined by \"Support: Core\" in this package,
+ e.g. \"RequestHeaderModifier\". All implementations
+ must support core filters. \n - Extended: Filter
+ types and their corresponding configuration defined
+ by \"Support: Extended\" in this package, e.g.
+ \"RequestMirror\". Implementers are encouraged
+ to support extended filters. \n - Implementation-specific:
+ Filters that are defined and supported by specific
+ vendors. In the future, filters showing convergence
+ in behavior across multiple implementations will
+ be considered for inclusion in extended or core
+ conformance levels. Filter-specific configuration
+ for such filters is specified using the ExtensionRef
+ field. `Type` should be set to \"ExtensionRef\"
+ for custom filters. \n Implementers are encouraged
+ to define custom implementation types to extend
+ the core API with implementation-specific behavior.
+ \n If a reference to a custom filter type cannot
+ be resolved, the filter MUST NOT be skipped. Instead,
+ requests that would have been processed by that
+ filter MUST receive a HTTP error response. \n
+ Note that values may be added to this enum, implementations
+ must ensure that unknown values will not cause
+ a crash. \n Unknown values here must result in
+ the implementation setting the Accepted Condition
+ for the Route to `status: False`, with a Reason
+ of `UnsupportedValue`."
+ enum:
+ - RequestHeaderModifier
+ - ResponseHeaderModifier
+ - RequestMirror
+ - RequestRedirect
+ - URLRewrite
+ - ExtensionRef
+ type: string
+ urlRewrite:
+ description: "URLRewrite defines a schema for a
+ filter that modifies a request during forwarding.
+ \n Support: Extended"
+ properties:
+ hostname:
+ description: "Hostname is the value to be used
+ to replace the Host header value during forwarding.
+ \n Support: Extended"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines a path rewrite. \n
+ Support: Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the
+ value with which to replace the full path
+ of a request during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies
+ the value with which to replace the prefix
+ match of a request during a rewrite or
+ redirect. For example, a request to \"/foo/bar\"
+ with a prefix match of \"/foo\" and a
+ ReplacePrefixMatch of \"/xyz\" would be
+ modified to \"/xyz/bar\". \n Note that
+ this matches the behavior of the PathPrefix
+ match type. This matches full path elements.
+ A path element refers to the list of labels
+ in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored.
+ For example, the paths `/abc`, `/abc/`,
+ and `/abc/def` would all match the prefix
+ `/abc`, but the path `/abcd` would not.
+ \n ReplacePrefixMatch is only compatible
+ with a `PathPrefix` HTTPRouteMatch. Using
+ any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`. \n Request Path
+ | Prefix Match | Replace Prefix | Modified
+ Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo |
+ /xyz/ | /xyz/bar /foo/bar |
+ /foo/ | /xyz | /xyz/bar
+ /foo/bar | /foo/ | /xyz/ |
+ /xyz/bar /foo | /foo |
+ /xyz | /xyz /foo/ | /foo
+ \ | /xyz | /xyz/ /foo/bar
+ \ | /foo | |
+ /bar /foo/ | /foo | | / /foo | /foo |
+ | / /foo/ | /foo
+ \ | / | / /foo |
+ /foo | / | /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path
+ modifier. Additional types may be added
+ in a future release of the API. \n Note
+ that values may be added to this enum,
+ implementations must ensure that unknown
+ values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`, with a Reason
+ of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified
+ when type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ?
+ has(self.replaceFullPath) : true'
+ - message: type must be 'ReplaceFullPath' when
+ replaceFullPath is set
+ rule: 'has(self.replaceFullPath) ? self.type
+ == ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified
+ when type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch''
+ ? has(self.replacePrefixMatch) : true'
+ - message: type must be 'ReplacePrefixMatch'
+ when replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ type: object
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: filter.requestHeaderModifier must be nil
+ if the filter.type is not RequestHeaderModifier
+ rule: '!(has(self.requestHeaderModifier) && self.type
+ != ''RequestHeaderModifier'')'
+ - message: filter.requestHeaderModifier must be specified
+ for RequestHeaderModifier filter.type
+ rule: '!(!has(self.requestHeaderModifier) && self.type
+ == ''RequestHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be nil
+ if the filter.type is not ResponseHeaderModifier
+ rule: '!(has(self.responseHeaderModifier) && self.type
+ != ''ResponseHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be specified
+ for ResponseHeaderModifier filter.type
+ rule: '!(!has(self.responseHeaderModifier) && self.type
+ == ''ResponseHeaderModifier'')'
+ - message: filter.requestMirror must be nil if the filter.type
+ is not RequestMirror
+ rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')'
+ - message: filter.requestMirror must be specified for
+ RequestMirror filter.type
+ rule: '!(!has(self.requestMirror) && self.type ==
+ ''RequestMirror'')'
+ - message: filter.requestRedirect must be nil if the
+ filter.type is not RequestRedirect
+ rule: '!(has(self.requestRedirect) && self.type !=
+ ''RequestRedirect'')'
+ - message: filter.requestRedirect must be specified
+ for RequestRedirect filter.type
+ rule: '!(!has(self.requestRedirect) && self.type ==
+ ''RequestRedirect'')'
+ - message: filter.urlRewrite must be nil if the filter.type
+ is not URLRewrite
+ rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')'
+ - message: filter.urlRewrite must be specified for URLRewrite
+ filter.type
+ rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')'
+ - message: filter.extensionRef must be nil if the filter.type
+ is not ExtensionRef
+ rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')'
+ - message: filter.extensionRef must be specified for
+ ExtensionRef filter.type
+ rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')'
+ maxItems: 16
+ type: array
+ x-kubernetes-validations:
+ - message: May specify either httpRouteFilterRequestRedirect
+ or httpRouteFilterRequestRewrite, but not both
+ rule: '!(self.exists(f, f.type == ''RequestRedirect'')
+ && self.exists(f, f.type == ''URLRewrite''))'
+ - message: May specify either httpRouteFilterRequestRedirect
+ or httpRouteFilterRequestRewrite, but not both
+ rule: '!(self.exists(f, f.type == ''RequestRedirect'')
+ && self.exists(f, f.type == ''URLRewrite''))'
+ - message: RequestHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestHeaderModifier').size()
+ <= 1
+ - message: ResponseHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'ResponseHeaderModifier').size()
+ <= 1
+ - message: RequestRedirect filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestRedirect').size()
+ <= 1
+ - message: URLRewrite filter cannot be repeated
+ rule: self.filter(f, f.type == 'URLRewrite').size()
+ <= 1
+ group:
+ default: ""
+ description: Group is the group of the referent. For example,
+ "gateway.networking.k8s.io". When unspecified or empty
+ string, core API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Service
+ description: "Kind is the Kubernetes resource kind of
+ the referent. For example \"Service\". \n Defaults to
+ \"Service\" when not specified. \n ExternalName services
+ can refer to CNAME DNS records that may live outside
+ of the cluster and as such are difficult to reason about
+ in terms of conformance. They also may not be safe to
+ forward to (see CVE-2021-25740 for more information).
+ Implementations SHOULD NOT support ExternalName Services.
+ \n Support: Core (Services with a type other than ExternalName)
+ \n Support: Implementation-specific (Services with type
+ ExternalName)"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the backend.
+ When unspecified, the local namespace is inferred. \n
+ Note that when a namespace different than the local
+ namespace is specified, a ReferenceGrant object is required
+ in the referent namespace to allow that namespace's
+ owner to accept the reference. See the ReferenceGrant
+ documentation for details. \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ port:
+ description: Port specifies the destination port number
+ to use for this resource. Port is required when the
+ referent is a Kubernetes Service. In this case, the
+ port number is the service port number, not the target
+ port. For other resources, destination port might be
+ derived from the referent resource or this field.
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ weight:
+ default: 1
+ description: "Weight specifies the proportion of requests
+ forwarded to the referenced backend. This is computed
+ as weight/(sum of all weights in this BackendRefs list).
+ For non-zero values, there may be some epsilon from
+ the exact proportion defined here depending on the precision
+ an implementation supports. Weight is not a percentage
+ and the sum of weights does not need to equal 100. \n
+ If only one backend is specified and it has a weight
+ greater than 0, 100% of the traffic is forwarded to
+ that backend. If weight is set to 0, no traffic should
+ be forwarded for this entry. If unspecified, weight
+ defaults to 1. \n Support for this field varies based
+ on the context where used."
+ format: int32
+ maximum: 1000000
+ minimum: 0
+ type: integer
+ required:
+ - name
+ type: object
+ x-kubernetes-validations:
+ - message: Must have port for Service reference
+ rule: '(size(self.group) == 0 && self.kind == ''Service'')
+ ? has(self.port) : true'
+ maxItems: 16
+ type: array
+ filters:
+ description: "Filters define the filters that are applied to
+ requests that match this rule. \n The effects of ordering
+ of multiple behaviors are currently unspecified. This can
+ change in the future based on feedback during the alpha stage.
+ \n Conformance-levels at this level are defined based on the
+ type of filter: \n - ALL core filters MUST be supported by
+ all implementations. - Implementers are encouraged to support
+ extended filters. - Implementation-specific custom filters
+ have no API guarantees across implementations. \n Specifying
+ the same filter multiple times is not supported unless explicitly
+ indicated in the filter. \n All filters are expected to be
+ compatible with each other except for the URLRewrite and RequestRedirect
+ filters, which may not be combined. If an implementation can
+ not support other combinations of filters, they must clearly
+ document that limitation. In cases where incompatible or unsupported
+ filters are specified and cause the `Accepted` condition to
+ be set to status `False`, implementations may use the `IncompatibleFilters`
+ reason to specify this configuration error. \n Support: Core"
+ items:
+ description: HTTPRouteFilter defines processing steps that
+ must be completed during the request or response lifecycle.
+ HTTPRouteFilters are meant as an extension point to express
+ processing that may be done in Gateway implementations.
+ Some examples include request or response modification,
+ implementing authentication strategies, rate-limiting, and
+ traffic shaping. API guarantee/conformance is defined based
+ on the type of the filter.
+ properties:
+ extensionRef:
+ description: "ExtensionRef is an optional, implementation-specific
+ extension to the \"filter\" behavior. For example,
+ resource \"myroutefilter\" in group \"networking.example.net\").
+ ExtensionRef MUST NOT be used for core and extended
+ filters. \n This filter can be used multiple times within
+ the same rule. \n Support: Implementation-specific"
+ properties:
+ group:
+ description: Group is the group of the referent. For
+ example, "gateway.networking.k8s.io". When unspecified
+ or empty string, core API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is kind of the referent. For example
+ "HTTPRoute" or "Service".
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - group
+ - kind
+ - name
+ type: object
+ requestHeaderModifier:
+ description: "RequestHeaderModifier defines a schema for
+ a filter that modifies request headers. \n Support:
+ Core"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It appends
+ to any existing values associated with the header
+ name. \n Input: GET /foo HTTP/1.1 my-header: foo
+ \n Config: add: - name: \"my-header\" value: \"bar,baz\"
+ \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from the
+ HTTP request before the action. The value of Remove
+ is a list of HTTP header names. Note that the header
+ names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2:
+ bar my-header3: baz \n Config: remove: [\"my-header1\",
+ \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2:
+ bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with the
+ given header (name, value) before the action. \n
+ Input: GET /foo HTTP/1.1 my-header: foo \n Config:
+ set: - name: \"my-header\" value: \"bar\" \n Output:
+ GET /foo HTTP/1.1 my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ requestMirror:
+ description: "RequestMirror defines a schema for a filter
+ that mirrors requests. Requests are sent to the specified
+ destination, but responses from that destination are
+ ignored. \n This filter can be used multiple times within
+ the same rule. Note that not all implementations will
+ be able to support mirroring to multiple backends. \n
+ Support: Extended"
+ properties:
+ backendRef:
+ description: "BackendRef references a resource where
+ mirrored requests are sent. \n Mirrored requests
+ must be sent only to a single destination endpoint
+ within this BackendRef, irrespective of how many
+ endpoints are present within this BackendRef. \n
+ If the referent cannot be found, this BackendRef
+ is invalid and must be dropped from the Gateway.
+ The controller must ensure the \"ResolvedRefs\"
+ condition on the Route status is set to `status:
+ False` and not configure this backend in the underlying
+ implementation. \n If there is a cross-namespace
+ reference to an *existing* object that is not allowed
+ by a ReferenceGrant, the controller must ensure
+ the \"ResolvedRefs\" condition on the Route is
+ set to `status: False`, with the \"RefNotPermitted\"
+ reason and not configure this backend in the underlying
+ implementation. \n In either error case, the Message
+ of the `ResolvedRefs` Condition should be used to
+ provide more detail about the problem. \n Support:
+ Extended for Kubernetes Service \n Support: Implementation-specific
+ for any other resource"
+ properties:
+ group:
+ default: ""
+ description: Group is the group of the referent.
+ For example, "gateway.networking.k8s.io". When
+ unspecified or empty string, core API group
+ is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Service
+ description: "Kind is the Kubernetes resource
+ kind of the referent. For example \"Service\".
+ \n Defaults to \"Service\" when not specified.
+ \n ExternalName services can refer to CNAME
+ DNS records that may live outside of the cluster
+ and as such are difficult to reason about in
+ terms of conformance. They also may not be safe
+ to forward to (see CVE-2021-25740 for more information).
+ Implementations SHOULD NOT support ExternalName
+ Services. \n Support: Core (Services with a
+ type other than ExternalName) \n Support: Implementation-specific
+ (Services with type ExternalName)"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the
+ backend. When unspecified, the local namespace
+ is inferred. \n Note that when a namespace different
+ than the local namespace is specified, a ReferenceGrant
+ object is required in the referent namespace
+ to allow that namespace's owner to accept the
+ reference. See the ReferenceGrant documentation
+ for details. \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ port:
+ description: Port specifies the destination port
+ number to use for this resource. Port is required
+ when the referent is a Kubernetes Service. In
+ this case, the port number is the service port
+ number, not the target port. For other resources,
+ destination port might be derived from the referent
+ resource or this field.
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ required:
+ - name
+ type: object
+ x-kubernetes-validations:
+ - message: Must have port for Service reference
+ rule: '(size(self.group) == 0 && self.kind == ''Service'')
+ ? has(self.port) : true'
+ required:
+ - backendRef
+ type: object
+ requestRedirect:
+ description: "RequestRedirect defines a schema for a filter
+ that responds to the request with an HTTP redirection.
+ \n Support: Core"
+ properties:
+ hostname:
+ description: "Hostname is the hostname to be used
+ in the value of the `Location` header in the response.
+ When empty, the hostname in the `Host` header of
+ the request is used. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines parameters used to modify
+ the path of the incoming request. The modified path
+ is then used to construct the `Location` header.
+ When empty, the request path is used as-is. \n Support:
+ Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the value
+ with which to replace the full path of a request
+ during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies the
+ value with which to replace the prefix match
+ of a request during a rewrite or redirect. For
+ example, a request to \"/foo/bar\" with a prefix
+ match of \"/foo\" and a ReplacePrefixMatch of
+ \"/xyz\" would be modified to \"/xyz/bar\".
+ \n Note that this matches the behavior of the
+ PathPrefix match type. This matches full path
+ elements. A path element refers to the list
+ of labels in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored. For
+ example, the paths `/abc`, `/abc/`, and `/abc/def`
+ would all match the prefix `/abc`, but the path
+ `/abcd` would not. \n ReplacePrefixMatch is
+ only compatible with a `PathPrefix` HTTPRouteMatch.
+ Using any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`. \n Request Path | Prefix
+ Match | Replace Prefix | Modified Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo | /xyz/
+ \ | /xyz/bar /foo/bar | /foo/ |
+ /xyz | /xyz/bar /foo/bar | /foo/
+ \ | /xyz/ | /xyz/bar /foo |
+ /foo | /xyz | /xyz /foo/ |
+ /foo | /xyz | /xyz/ /foo/bar
+ \ | /foo | | /bar
+ /foo/ | /foo |
+ | / /foo | /foo |
+ | / /foo/ | /foo | / |
+ / /foo | /foo | / |
+ /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path modifier.
+ Additional types may be added in a future release
+ of the API. \n Note that values may be added
+ to this enum, implementations must ensure that
+ unknown values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`, with a Reason of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified when
+ type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath)
+ : true'
+ - message: type must be 'ReplaceFullPath' when replaceFullPath
+ is set
+ rule: 'has(self.replaceFullPath) ? self.type ==
+ ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified when
+ type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch)
+ : true'
+ - message: type must be 'ReplacePrefixMatch' when
+ replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ port:
+ description: "Port is the port to be used in the value
+ of the `Location` header in the response. \n If
+ no port is specified, the redirect port MUST be
+ derived using the following rules: \n * If redirect
+ scheme is not-empty, the redirect port MUST be the
+ well-known port associated with the redirect scheme.
+ Specifically \"http\" to port 80 and \"https\" to
+ port 443. If the redirect scheme does not have a
+ well-known port, the listener port of the Gateway
+ SHOULD be used. * If redirect scheme is empty, the
+ redirect port MUST be the Gateway Listener port.
+ \n Implementations SHOULD NOT add the port number
+ in the 'Location' header in the following cases:
+ \n * A Location header that will use HTTP (whether
+ that is determined via the Listener protocol or
+ the Scheme field) _and_ use port 80. * A Location
+ header that will use HTTPS (whether that is determined
+ via the Listener protocol or the Scheme field) _and_
+ use port 443. \n Support: Extended"
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ scheme:
+ description: "Scheme is the scheme to be used in the
+ value of the `Location` header in the response.
+ When empty, the scheme of the request is used. \n
+ Scheme redirects can affect the port of the redirect,
+ for more information, refer to the documentation
+ for the port field of this filter. \n Note that
+ values may be added to this enum, implementations
+ must ensure that unknown values will not cause a
+ crash. \n Unknown values here must result in the
+ implementation setting the Accepted Condition for
+ the Route to `status: False`, with a Reason of `UnsupportedValue`.
+ \n Support: Extended"
+ enum:
+ - http
+ - https
+ type: string
+ statusCode:
+ default: 302
+ description: "StatusCode is the HTTP status code to
+ be used in response. \n Note that values may be
+ added to this enum, implementations must ensure
+ that unknown values will not cause a crash. \n Unknown
+ values here must result in the implementation setting
+ the Accepted Condition for the Route to `status:
+ False`, with a Reason of `UnsupportedValue`. \n
+ Support: Core"
+ enum:
+ - 301
+ - 302
+ type: integer
+ type: object
+ responseHeaderModifier:
+ description: "ResponseHeaderModifier defines a schema
+ for a filter that modifies response headers. \n Support:
+ Extended"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It appends
+ to any existing values associated with the header
+ name. \n Input: GET /foo HTTP/1.1 my-header: foo
+ \n Config: add: - name: \"my-header\" value: \"bar,baz\"
+ \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from the
+ HTTP request before the action. The value of Remove
+ is a list of HTTP header names. Note that the header
+ names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2:
+ bar my-header3: baz \n Config: remove: [\"my-header1\",
+ \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2:
+ bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with the
+ given header (name, value) before the action. \n
+ Input: GET /foo HTTP/1.1 my-header: foo \n Config:
+ set: - name: \"my-header\" value: \"bar\" \n Output:
+ GET /foo HTTP/1.1 my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ type:
+ description: "Type identifies the type of filter to apply.
+ As with other API fields, types are classified into
+ three conformance levels: \n - Core: Filter types and
+ their corresponding configuration defined by \"Support:
+ Core\" in this package, e.g. \"RequestHeaderModifier\".
+ All implementations must support core filters. \n -
+ Extended: Filter types and their corresponding configuration
+ defined by \"Support: Extended\" in this package, e.g.
+ \"RequestMirror\". Implementers are encouraged to support
+ extended filters. \n - Implementation-specific: Filters
+ that are defined and supported by specific vendors.
+ In the future, filters showing convergence in behavior
+ across multiple implementations will be considered for
+ inclusion in extended or core conformance levels. Filter-specific
+ configuration for such filters is specified using the
+ ExtensionRef field. `Type` should be set to \"ExtensionRef\"
+ for custom filters. \n Implementers are encouraged to
+ define custom implementation types to extend the core
+ API with implementation-specific behavior. \n If a reference
+ to a custom filter type cannot be resolved, the filter
+ MUST NOT be skipped. Instead, requests that would have
+ been processed by that filter MUST receive a HTTP error
+ response. \n Note that values may be added to this enum,
+ implementations must ensure that unknown values will
+ not cause a crash. \n Unknown values here must result
+ in the implementation setting the Accepted Condition
+ for the Route to `status: False`, with a Reason of `UnsupportedValue`."
+ enum:
+ - RequestHeaderModifier
+ - ResponseHeaderModifier
+ - RequestMirror
+ - RequestRedirect
+ - URLRewrite
+ - ExtensionRef
+ type: string
+ urlRewrite:
+ description: "URLRewrite defines a schema for a filter
+ that modifies a request during forwarding. \n Support:
+ Extended"
+ properties:
+ hostname:
+ description: "Hostname is the value to be used to
+ replace the Host header value during forwarding.
+ \n Support: Extended"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines a path rewrite. \n Support:
+ Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the value
+ with which to replace the full path of a request
+ during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies the
+ value with which to replace the prefix match
+ of a request during a rewrite or redirect. For
+ example, a request to \"/foo/bar\" with a prefix
+ match of \"/foo\" and a ReplacePrefixMatch of
+ \"/xyz\" would be modified to \"/xyz/bar\".
+ \n Note that this matches the behavior of the
+ PathPrefix match type. This matches full path
+ elements. A path element refers to the list
+ of labels in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored. For
+ example, the paths `/abc`, `/abc/`, and `/abc/def`
+ would all match the prefix `/abc`, but the path
+ `/abcd` would not. \n ReplacePrefixMatch is
+ only compatible with a `PathPrefix` HTTPRouteMatch.
+ Using any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`. \n Request Path | Prefix
+ Match | Replace Prefix | Modified Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo | /xyz/
+ \ | /xyz/bar /foo/bar | /foo/ |
+ /xyz | /xyz/bar /foo/bar | /foo/
+ \ | /xyz/ | /xyz/bar /foo |
+ /foo | /xyz | /xyz /foo/ |
+ /foo | /xyz | /xyz/ /foo/bar
+ \ | /foo | | /bar
+ /foo/ | /foo |
+ | / /foo | /foo |
+ | / /foo/ | /foo | / |
+ / /foo | /foo | / |
+ /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path modifier.
+ Additional types may be added in a future release
+ of the API. \n Note that values may be added
+ to this enum, implementations must ensure that
+ unknown values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`, with a Reason of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified when
+ type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath)
+ : true'
+ - message: type must be 'ReplaceFullPath' when replaceFullPath
+ is set
+ rule: 'has(self.replaceFullPath) ? self.type ==
+ ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified when
+ type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch)
+ : true'
+ - message: type must be 'ReplacePrefixMatch' when
+ replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ type: object
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: filter.requestHeaderModifier must be nil if the
+ filter.type is not RequestHeaderModifier
+ rule: '!(has(self.requestHeaderModifier) && self.type !=
+ ''RequestHeaderModifier'')'
+ - message: filter.requestHeaderModifier must be specified
+ for RequestHeaderModifier filter.type
+ rule: '!(!has(self.requestHeaderModifier) && self.type ==
+ ''RequestHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be nil if the
+ filter.type is not ResponseHeaderModifier
+ rule: '!(has(self.responseHeaderModifier) && self.type !=
+ ''ResponseHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be specified
+ for ResponseHeaderModifier filter.type
+ rule: '!(!has(self.responseHeaderModifier) && self.type
+ == ''ResponseHeaderModifier'')'
+ - message: filter.requestMirror must be nil if the filter.type
+ is not RequestMirror
+ rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')'
+ - message: filter.requestMirror must be specified for RequestMirror
+ filter.type
+ rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')'
+ - message: filter.requestRedirect must be nil if the filter.type
+ is not RequestRedirect
+ rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')'
+ - message: filter.requestRedirect must be specified for RequestRedirect
+ filter.type
+ rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')'
+ - message: filter.urlRewrite must be nil if the filter.type
+ is not URLRewrite
+ rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')'
+ - message: filter.urlRewrite must be specified for URLRewrite
+ filter.type
+ rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')'
+ - message: filter.extensionRef must be nil if the filter.type
+ is not ExtensionRef
+ rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')'
+ - message: filter.extensionRef must be specified for ExtensionRef
+ filter.type
+ rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')'
+ maxItems: 16
+ type: array
+ x-kubernetes-validations:
+ - message: May specify either httpRouteFilterRequestRedirect
+ or httpRouteFilterRequestRewrite, but not both
+ rule: '!(self.exists(f, f.type == ''RequestRedirect'') &&
+ self.exists(f, f.type == ''URLRewrite''))'
+ - message: RequestHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestHeaderModifier').size()
+ <= 1
+ - message: ResponseHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'ResponseHeaderModifier').size()
+ <= 1
+ - message: RequestRedirect filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestRedirect').size() <=
+ 1
+ - message: URLRewrite filter cannot be repeated
+ rule: self.filter(f, f.type == 'URLRewrite').size() <= 1
+ matches:
+ default:
+ - path:
+ type: PathPrefix
+ value: /
+ description: "Matches define conditions used for matching the
+ rule against incoming HTTP requests. Each match is independent,
+ i.e. this rule will be matched if **any** one of the matches
+ is satisfied. \n For example, take the following matches configuration:
+ \n ``` matches: - path: value: \"/foo\" headers: - name: \"version\"
+ value: \"v2\" - path: value: \"/v2/foo\" ``` \n For a request
+ to match against this rule, a request must satisfy EITHER
+ of the two conditions: \n - path prefixed with `/foo` AND
+ contains the header `version: v2` - path prefix of `/v2/foo`
+ \n See the documentation for HTTPRouteMatch on how to specify
+ multiple match conditions that should be ANDed together. \n
+ If no matches are specified, the default is a prefix path
+ match on \"/\", which has the effect of matching every HTTP
+ request. \n Proxy or Load Balancer routing configuration generated
+ from HTTPRoutes MUST prioritize matches based on the following
+ criteria, continuing on ties. Across all rules specified on
+ applicable Routes, precedence must be given to the match having:
+ \n * \"Exact\" path match. * \"Prefix\" path match with largest
+ number of characters. * Method match. * Largest number of
+ header matches. * Largest number of query param matches. \n
+ Note: The precedence of RegularExpression path matches are
+ implementation-specific. \n If ties still exist across multiple
+ Routes, matching precedence MUST be determined in order of
+ the following criteria, continuing on ties: \n * The oldest
+ Route based on creation timestamp. * The Route appearing first
+ in alphabetical order by \"{namespace}/{name}\". \n If ties
+ still exist within an HTTPRoute, matching precedence MUST
+ be granted to the FIRST matching rule (in list order) with
+ a match meeting the above criteria. \n When no rules matching
+ a request have been successfully attached to the parent a
+ request is coming from, a HTTP 404 status code MUST be returned."
+ items:
+ description: "HTTPRouteMatch defines the predicate used to
+ match requests to a given action. Multiple match types are
+ ANDed together, i.e. the match will evaluate to true only
+ if all conditions are satisfied. \n For example, the match
+ below will match a HTTP request only if its path starts
+ with `/foo` AND it contains the `version: v1` header: \n
+ ``` match: \n path: value: \"/foo\" headers: - name: \"version\"
+ value \"v1\" \n ```"
+ properties:
+ headers:
+ description: Headers specifies HTTP request header matchers.
+ Multiple match values are ANDed together, meaning, a
+ request must match all the specified headers to select
+ the route.
+ items:
+ description: HTTPHeaderMatch describes how to select
+ a HTTP route by matching HTTP request headers.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case insensitive.
+ (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent header
+ names, only the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST be
+ ignored. Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered equivalent.
+ \n When a header is repeated in an HTTP request,
+ it is implementation-specific behavior as to how
+ this is represented. Generally, proxies should
+ follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2
+ regarding processing a repeated header, with special
+ handling for \"Set-Cookie\"."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ type:
+ default: Exact
+ description: "Type specifies how to match against
+ the value of the header. \n Support: Core (Exact)
+ \n Support: Implementation-specific (RegularExpression)
+ \n Since RegularExpression HeaderMatchType has
+ implementation-specific conformance, implementations
+ can support POSIX, PCRE or any other dialects
+ of regular expressions. Please read the implementation's
+ documentation to determine the supported dialect."
+ enum:
+ - Exact
+ - RegularExpression
+ type: string
+ value:
+ description: Value is the value of HTTP Header to
+ be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ method:
+ description: "Method specifies HTTP method matcher. When
+ specified, this route will be matched only if the request
+ has the specified method. \n Support: Extended"
+ enum:
+ - GET
+ - HEAD
+ - POST
+ - PUT
+ - DELETE
+ - CONNECT
+ - OPTIONS
+ - TRACE
+ - PATCH
+ type: string
+ path:
+ default:
+ type: PathPrefix
+ value: /
+ description: Path specifies a HTTP request path matcher.
+ If this field is not specified, a default prefix match
+ on the "/" path is provided.
+ properties:
+ type:
+ default: PathPrefix
+ description: "Type specifies how to match against
+ the path Value. \n Support: Core (Exact, PathPrefix)
+ \n Support: Implementation-specific (RegularExpression)"
+ enum:
+ - Exact
+ - PathPrefix
+ - RegularExpression
+ type: string
+ value:
+ default: /
+ description: Value of the HTTP path to match against.
+ maxLength: 1024
+ type: string
+ type: object
+ x-kubernetes-validations:
+ - message: value must be an absolute path and start with
+ '/' when type one of ['Exact', 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'')
+ : true'
+ - message: must not contain '//' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'')
+ : true'
+ - message: must not contain '/./' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'')
+ : true'
+ - message: must not contain '/../' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'')
+ : true'
+ - message: must not contain '%2f' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'')
+ : true'
+ - message: must not contain '%2F' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'')
+ : true'
+ - message: must not contain '#' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'')
+ : true'
+ - message: must not end with '/..' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'')
+ : true'
+ - message: must not end with '/.' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'')
+ : true'
+ - message: type must be one of ['Exact', 'PathPrefix',
+ 'RegularExpression']
+ rule: self.type in ['Exact','PathPrefix'] || self.type
+ == 'RegularExpression'
+ - message: must only contain valid characters (matching
+ ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$)
+ for types ['Exact', 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""")
+ : true'
+ queryParams:
+ description: "QueryParams specifies HTTP query parameter
+ matchers. Multiple match values are ANDed together,
+ meaning, a request must match all the specified query
+ parameters to select the route. \n Support: Extended"
+ items:
+ description: HTTPQueryParamMatch describes how to select
+ a HTTP route by matching HTTP query parameters.
+ properties:
+ name:
+ description: "Name is the name of the HTTP query
+ param to be matched. This must be an exact string
+ match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3).
+ \n If multiple entries specify equivalent query
+ param names, only the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent query param name MUST
+ be ignored. \n If a query param is repeated in
+ an HTTP request, the behavior is purposely left
+ undefined, since different data planes have different
+ capabilities. However, it is *recommended* that
+ implementations should match against the first
+ value of the param if the data plane supports
+ it, as this behavior is expected in other load
+ balancing contexts outside of the Gateway API.
+ \n Users SHOULD NOT route traffic based on repeated
+ query params to guard themselves against potential
+ differences in the implementations."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ type:
+ default: Exact
+ description: "Type specifies how to match against
+ the value of the query parameter. \n Support:
+ Extended (Exact) \n Support: Implementation-specific
+ (RegularExpression) \n Since RegularExpression
+ QueryParamMatchType has Implementation-specific
+ conformance, implementations can support POSIX,
+ PCRE or any other dialects of regular expressions.
+ Please read the implementation's documentation
+ to determine the supported dialect."
+ enum:
+ - Exact
+ - RegularExpression
+ type: string
+ value:
+ description: Value is the value of HTTP query param
+ to be matched.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ maxItems: 8
+ type: array
+ type: object
+ x-kubernetes-validations:
+ - message: RequestRedirect filter must not be used together with
+ backendRefs
+ rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ?
+ (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))):
+ true'
+ - message: When using RequestRedirect filter with path.replacePrefixMatch,
+ exactly one PathPrefix match must be specified
+ rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect)
+ && has(f.requestRedirect.path) && f.requestRedirect.path.type
+ == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch)))
+ ? ((size(self.matches) != 1 || !has(self.matches[0].path) ||
+ self.matches[0].path.type != ''PathPrefix'') ? false : true)
+ : true'
+ - message: When using URLRewrite filter with path.replacePrefixMatch,
+ exactly one PathPrefix match must be specified
+ rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite)
+ && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch''
+ && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches)
+ != 1 || !has(self.matches[0].path) || self.matches[0].path.type
+ != ''PathPrefix'') ? false : true) : true'
+ - message: Within backendRefs, when using RequestRedirect filter
+ with path.replacePrefixMatch, exactly one PathPrefix match must
+ be specified
+ rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b,
+ (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect)
+ && has(f.requestRedirect.path) && f.requestRedirect.path.type
+ == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch)))
+ )) ? ((size(self.matches) != 1 || !has(self.matches[0].path)
+ || self.matches[0].path.type != ''PathPrefix'') ? false : true)
+ : true'
+ - message: Within backendRefs, When using URLRewrite filter with
+ path.replacePrefixMatch, exactly one PathPrefix match must be
+ specified
+ rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b,
+ (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite)
+ && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch''
+ && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches)
+ != 1 || !has(self.matches[0].path) || self.matches[0].path.type
+ != ''PathPrefix'') ? false : true) : true'
+ maxItems: 16
+ type: array
+ type: object
+ status:
+ description: Status defines the current state of HTTPRoute.
+ properties:
+ parents:
+ description: "Parents is a list of parent resources (usually Gateways)
+ that are associated with the route, and the status of the route
+ with respect to each parent. When this route attaches to a parent,
+ the controller that manages the parent must add an entry to this
+ list when the controller first sees the route and should update
+ the entry as appropriate when the route or gateway is modified.
+ \n Note that parent references that cannot be resolved by an implementation
+ of this API will not be added to this list. Implementations of this
+ API can only populate Route status for the Gateways/parent resources
+ they are responsible for. \n A maximum of 32 Gateways will be represented
+ in this list. An empty list means the route has not been attached
+ to any Gateway."
+ items:
+ description: RouteParentStatus describes the status of a route with
+ respect to an associated Parent.
+ properties:
+ conditions:
+ description: "Conditions describes the status of the route with
+ respect to the Gateway. Note that the route's availability
+ is also subject to the Gateway's own status conditions and
+ listener status. \n If the Route's ParentRef specifies an
+ existing Gateway that supports Routes of this kind AND that
+ Gateway's controller has sufficient access, then that Gateway's
+ controller MUST set the \"Accepted\" condition on the Route,
+ to indicate whether the route has been accepted or rejected
+ by the Gateway, and why. \n A Route MUST be considered \"Accepted\"
+ if at least one of the Route's rules is implemented by the
+ Gateway. \n There are a number of cases where the \"Accepted\"
+ condition may not be set due to lack of controller visibility,
+ that includes when: \n * The Route refers to a non-existent
+ parent. * The Route is of a type that the controller does
+ not support. * The Route is in a namespace the controller
+ does not have access to."
+ items:
+ description: "Condition contains details for one aspect of
+ the current state of this API Resource. --- This struct
+ is intended for direct use as an array at the field path
+ .status.conditions. For example, \n type FooStatus struct{
+ // Represents the observations of a foo's current state.
+ // Known .status.conditions.type are: \"Available\", \"Progressing\",
+ and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields
+ }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should
+ be when the underlying condition changed. If that is
+ not known, then using the time when the API field changed
+ is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance,
+ if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the
+ current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier
+ indicating the reason for the condition's last transition.
+ Producers of specific condition types may define expected
+ values and meanings for this field, and whether the
+ values are considered a guaranteed API. The value should
+ be a CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False,
+ Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across
+ resources like Available, but because arbitrary conditions
+ can be useful (see .node.status.conditions), the ability
+ to deconflict is important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ controllerName:
+ description: "ControllerName is a domain/path string that indicates
+ the name of the controller that wrote this status. This corresponds
+ with the controllerName field on GatewayClass. \n Example:
+ \"example.net/gateway-controller\". \n The format of this
+ field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid
+ Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
+ \n Controllers MUST populate this field when writing status.
+ Controllers should ensure that entries to status populated
+ with their ControllerName are cleaned up when they are no
+ longer necessary."
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ parentRef:
+ description: ParentRef corresponds with a ParentRef in the spec
+ that this RouteParentStatus struct describes the status of.
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: "Group is the group of the referent. When unspecified,
+ \"gateway.networking.k8s.io\" is inferred. To set the
+ core API group (such as for a \"Service\" kind referent),
+ Group must be explicitly set to \"\" (empty string). \n
+ Support: Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Gateway
+ description: "Kind is kind of the referent. \n There are
+ two kinds of parent resources with \"Core\" support: \n
+ * Gateway (Gateway conformance profile) * Service (Mesh
+ conformance profile, experimental, ClusterIP Services
+ only) \n Support for other resources is Implementation-Specific."
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: "Name is the name of the referent. \n Support:
+ Core"
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referent.
+ When unspecified, this refers to the local namespace of
+ the Route. \n Note that there are specific rules for ParentRefs
+ which cross namespace boundaries. Cross-namespace references
+ are only valid if they are explicitly allowed by something
+ in the namespace they are referring to. For example: Gateway
+ has the AllowedRoutes field, and ReferenceGrant provides
+ a generic way to enable any other kind of cross-namespace
+ reference. \n \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ sectionName:
+ description: "SectionName is the name of a section within
+ the target resource. In the following resources, SectionName
+ is interpreted as the following: \n * Gateway: Listener
+ Name. When both Port (experimental) and SectionName are
+ specified, the name and port of the selected listener
+ must match both specified values. * Service: Port Name.
+ When both Port (experimental) and SectionName are specified,
+ the name and port of the selected listener must match
+ both specified values. Note that attaching Routes to Services
+ as Parents is part of experimental Mesh support and is
+ not supported for any other purpose. \n Implementations
+ MAY choose to support attaching Routes to other resources.
+ If that is the case, they MUST clearly document how SectionName
+ is interpreted. \n When unspecified (empty string), this
+ will reference the entire resource. For the purpose of
+ status, an attachment is considered successful if at least
+ one section in the parent resource accepts it. For example,
+ Gateway listeners can restrict which Routes can attach
+ to them by Route kind, namespace, or hostname. If 1 of
+ 2 Gateway listeners accept attachment from the referencing
+ Route, the Route MUST be considered successfully attached.
+ If no Gateway listeners accept attachment from this Route,
+ the Route MUST be considered detached from the Gateway.
+ \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ required:
+ - name
+ type: object
+ required:
+ - controllerName
+ - parentRef
+ type: object
+ maxItems: 32
+ type: array
+ required:
+ - parents
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
+ - additionalPrinterColumns:
+ - jsonPath: .spec.hostnames
+ name: Hostnames
+ type: string
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: HTTPRoute provides a way to route HTTP requests. This includes
+ the capability to match requests by hostname, path, header, or query param.
+ Filters can be used to specify additional processing steps. Backends specify
+ where matching requests should be routed.
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of HTTPRoute.
+ properties:
+ hostnames:
+ description: "Hostnames defines a set of hostnames that should match
+ against the HTTP Host header to select a HTTPRoute used to process
+ the request. Implementations MUST ignore any port value specified
+ in the HTTP Host header while performing a match and (absent of
+ any applicable header modification configuration) MUST forward this
+ header unmodified to the backend. \n Valid values for Hostnames
+ are determined by RFC 1123 definition of a hostname with 2 notable
+ exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed
+ with a wildcard label (`*.`). The wildcard label must appear by
+ itself as the first label. \n If a hostname is specified by both
+ the Listener and HTTPRoute, there must be at least one intersecting
+ hostname for the HTTPRoute to be attached to the Listener. For example:
+ \n * A Listener with `test.example.com` as the hostname matches
+ HTTPRoutes that have either not specified any hostnames, or have
+ specified at least one of `test.example.com` or `*.example.com`.
+ * A Listener with `*.example.com` as the hostname matches HTTPRoutes
+ that have either not specified any hostnames or have specified at
+ least one hostname that matches the Listener hostname. For example,
+ `*.example.com`, `test.example.com`, and `foo.test.example.com`
+ would all match. On the other hand, `example.com` and `test.example.net`
+ would not match. \n Hostnames that are prefixed with a wildcard
+ label (`*.`) are interpreted as a suffix match. That means that
+ a match for `*.example.com` would match both `test.example.com`,
+ and `foo.test.example.com`, but not `example.com`. \n If both the
+ Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames
+ that do not match the Listener hostname MUST be ignored. For example,
+ if a Listener specified `*.example.com`, and the HTTPRoute specified
+ `test.example.com` and `test.example.net`, `test.example.net` must
+ not be considered for a match. \n If both the Listener and HTTPRoute
+ have specified hostnames, and none match with the criteria above,
+ then the HTTPRoute is not accepted. The implementation must raise
+ an 'Accepted' Condition with a status of `False` in the corresponding
+ RouteParentStatus. \n In the event that multiple HTTPRoutes specify
+ intersecting hostnames (e.g. overlapping wildcard matching and exact
+ matching hostnames), precedence must be given to rules from the
+ HTTPRoute with the largest number of: \n * Characters in a matching
+ non-wildcard hostname. * Characters in a matching hostname. \n If
+ ties exist across multiple Routes, the matching precedence rules
+ for HTTPRouteMatches takes over. \n Support: Core"
+ items:
+ description: "Hostname is the fully qualified domain name of a network
+ host. This matches the RFC 1123 definition of a hostname with
+ 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname
+ may be prefixed with a wildcard label (`*.`). The wildcard label
+ must appear by itself as the first label. \n Hostname can be \"precise\"
+ which is a domain name without the terminating dot of a network
+ host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain
+ name prefixed with a single wildcard label (e.g. `*.example.com`).
+ \n Note that as per RFC1035 and RFC1123, a *label* must consist
+ of lower case alphanumeric characters or '-', and must start and
+ end with an alphanumeric character. No other punctuation is allowed."
+ maxLength: 253
+ minLength: 1
+ pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ maxItems: 16
+ type: array
+ parentRefs:
+ description: "ParentRefs references the resources (usually Gateways)
+ that a Route wants to be attached to. Note that the referenced parent
+ resource needs to allow this for the attachment to be complete.
+ For Gateways, that means the Gateway needs to allow attachment from
+ Routes of this kind and namespace. For Services, that means the
+ Service must either be in the same namespace for a \"producer\"
+ route, or the mesh implementation must support and allow \"consumer\"
+ routes for the referenced Service. ReferenceGrant is not applicable
+ for governing ParentRefs to Services - it is not possible to create
+ a \"producer\" route for a Service in a different namespace from
+ the Route. \n There are two kinds of parent resources with \"Core\"
+ support: \n * Gateway (Gateway conformance profile) This API may
+ be extended in the future to support additional kinds of parent
+ resources. \n ParentRefs must be _distinct_. This means either that:
+ \n * They select different objects. If this is the case, then parentRef
+ entries are distinct. In terms of fields, this means that the multi-part
+ key defined by `group`, `kind`, `namespace`, and `name` must be
+ unique across all parentRef entries in the Route. * They do not
+ select different objects, but for each optional field used, each
+ ParentRef that selects the same object must set the same set of
+ optional fields to different values. If one ParentRef sets a combination
+ of optional fields, all must set the same combination. \n Some examples:
+ \n * If one ParentRef sets `sectionName`, all ParentRefs referencing
+ the same object must also set `sectionName`. * If one ParentRef
+ sets `port`, all ParentRefs referencing the same object must also
+ set `port`. * If one ParentRef sets `sectionName` and `port`, all
+ ParentRefs referencing the same object must also set `sectionName`
+ and `port`. \n It is possible to separately reference multiple distinct
+ objects that may be collapsed by an implementation. For example,
+ some implementations may choose to merge compatible Gateway Listeners
+ together. If that is the case, the list of routes attached to those
+ resources should also be merged. \n Note that for ParentRefs that
+ cross namespace boundaries, there are specific rules. Cross-namespace
+ references are only valid if they are explicitly allowed by something
+ in the namespace they are referring to. For example, Gateway has
+ the AllowedRoutes field, and ReferenceGrant provides a generic way
+ to enable other kinds of cross-namespace reference. \n \n "
+ items:
+ description: "ParentReference identifies an API object (usually
+ a Gateway) that can be considered a parent of this resource (usually
+ a route). There are two kinds of parent resources with \"Core\"
+ support: \n * Gateway (Gateway conformance profile) * Service
+ (Mesh conformance profile, experimental, ClusterIP Services only)
+ \n This API may be extended in the future to support additional
+ kinds of parent resources. \n The API object must be valid in
+ the cluster; the Group and Kind must be registered in the cluster
+ for this reference to be valid."
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: "Group is the group of the referent. When unspecified,
+ \"gateway.networking.k8s.io\" is inferred. To set the core
+ API group (such as for a \"Service\" kind referent), Group
+ must be explicitly set to \"\" (empty string). \n Support:
+ Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Gateway
+ description: "Kind is kind of the referent. \n There are two
+ kinds of parent resources with \"Core\" support: \n * Gateway
+ (Gateway conformance profile) * Service (Mesh conformance
+ profile, experimental, ClusterIP Services only) \n Support
+ for other resources is Implementation-Specific."
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: "Name is the name of the referent. \n Support:
+ Core"
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referent. When
+ unspecified, this refers to the local namespace of the Route.
+ \n Note that there are specific rules for ParentRefs which
+ cross namespace boundaries. Cross-namespace references are
+ only valid if they are explicitly allowed by something in
+ the namespace they are referring to. For example: Gateway
+ has the AllowedRoutes field, and ReferenceGrant provides a
+ generic way to enable any other kind of cross-namespace reference.
+ \n \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ sectionName:
+ description: "SectionName is the name of a section within the
+ target resource. In the following resources, SectionName is
+ interpreted as the following: \n * Gateway: Listener Name.
+ When both Port (experimental) and SectionName are specified,
+ the name and port of the selected listener must match both
+ specified values. * Service: Port Name. When both Port (experimental)
+ and SectionName are specified, the name and port of the selected
+ listener must match both specified values. Note that attaching
+ Routes to Services as Parents is part of experimental Mesh
+ support and is not supported for any other purpose. \n Implementations
+ MAY choose to support attaching Routes to other resources.
+ If that is the case, they MUST clearly document how SectionName
+ is interpreted. \n When unspecified (empty string), this will
+ reference the entire resource. For the purpose of status,
+ an attachment is considered successful if at least one section
+ in the parent resource accepts it. For example, Gateway listeners
+ can restrict which Routes can attach to them by Route kind,
+ namespace, or hostname. If 1 of 2 Gateway listeners accept
+ attachment from the referencing Route, the Route MUST be considered
+ successfully attached. If no Gateway listeners accept attachment
+ from this Route, the Route MUST be considered detached from
+ the Gateway. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ required:
+ - name
+ type: object
+ maxItems: 32
+ type: array
+ x-kubernetes-validations:
+ - message: sectionName must be specified when parentRefs includes
+ 2 or more references to the same parent
+ rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind
+ == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__)
+ || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__
+ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) &&
+ p1.__namespace__ == p2.__namespace__ )) ? ((!has(p1.sectionName)
+ || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName
+ == '''')) : true))'
+ - message: sectionName must be unique when parentRefs includes 2 or
+ more references to the same parent
+ rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind
+ == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__)
+ || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__
+ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) &&
+ p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName)
+ || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName
+ == '')) || (has(p1.sectionName) && has(p2.sectionName) && p1.sectionName
+ == p2.sectionName))))
+ rules:
+ default:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /
+ description: Rules are a list of HTTP matchers, filters and actions.
+ items:
+ description: HTTPRouteRule defines semantics for matching an HTTP
+ request based on conditions (matches), processing it (filters),
+ and forwarding the request to an API object (backendRefs).
+ properties:
+ backendRefs:
+ description: "BackendRefs defines the backend(s) where matching
+ requests should be sent. \n Failure behavior here depends
+ on how many BackendRefs are specified and how many are invalid.
+ \n If *all* entries in BackendRefs are invalid, and there
+ are also no filters specified in this route rule, *all* traffic
+ which matches this rule MUST receive a 500 status code. \n
+ See the HTTPBackendRef definition for the rules about what
+ makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef
+ is invalid, 500 status codes MUST be returned for requests
+ that would have otherwise been routed to an invalid backend.
+ If multiple backends are specified, and some are invalid,
+ the proportion of requests that would otherwise have been
+ routed to an invalid backend MUST receive a 500 status code.
+ \n For example, if two backends are specified with equal weights,
+ and one is invalid, 50 percent of traffic must receive a 500.
+ Implementations may choose how that 50 percent is determined.
+ \n Support: Core for Kubernetes Service \n Support: Extended
+ for Kubernetes ServiceImport \n Support: Implementation-specific
+ for any other resource \n Support for weight: Core"
+ items:
+ description: "HTTPBackendRef defines how a HTTPRoute forwards
+ a HTTP request. \n Note that when a namespace different
+ than the local namespace is specified, a ReferenceGrant
+ object is required in the referent namespace to allow that
+ namespace's owner to accept the reference. See the ReferenceGrant
+ documentation for details. \n
+ \n When the BackendRef points to a Kubernetes Service, implementations
+ SHOULD honor the appProtocol field if it is set for the
+ target Service Port. \n Implementations supporting appProtocol
+ SHOULD recognize the Kubernetes Standard Application Protocols
+ defined in KEP-3726. \n If a Service appProtocol isn't specified,
+ an implementation MAY infer the backend protocol through
+ its own means. Implementations MAY infer the protocol from
+ the Route type referring to the backend Service. \n If a
+ Route is not able to send traffic to the backend using the
+ specified protocol then the backend is considered invalid.
+ Implementations MUST set the \"ResolvedRefs\" condition
+ to \"False\" with the \"UnsupportedProtocol\" reason. \n
+ "
+ properties:
+ filters:
+ description: "Filters defined at this level should be
+ executed if and only if the request is being forwarded
+ to the backend defined here. \n Support: Implementation-specific
+ (For broader support of filters, use the Filters field
+ in HTTPRouteRule.)"
+ items:
+ description: HTTPRouteFilter defines processing steps
+ that must be completed during the request or response
+ lifecycle. HTTPRouteFilters are meant as an extension
+ point to express processing that may be done in Gateway
+ implementations. Some examples include request or
+ response modification, implementing authentication
+ strategies, rate-limiting, and traffic shaping. API
+ guarantee/conformance is defined based on the type
+ of the filter.
+ properties:
+ extensionRef:
+ description: "ExtensionRef is an optional, implementation-specific
+ extension to the \"filter\" behavior. For example,
+ resource \"myroutefilter\" in group \"networking.example.net\").
+ ExtensionRef MUST NOT be used for core and extended
+ filters. \n This filter can be used multiple times
+ within the same rule. \n Support: Implementation-specific"
+ properties:
+ group:
+ description: Group is the group of the referent.
+ For example, "gateway.networking.k8s.io".
+ When unspecified or empty string, core API
+ group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is kind of the referent. For
+ example "HTTPRoute" or "Service".
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - group
+ - kind
+ - name
+ type: object
+ requestHeaderModifier:
+ description: "RequestHeaderModifier defines a schema
+ for a filter that modifies request headers. \n
+ Support: Core"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It
+ appends to any existing values associated
+ with the header name. \n Input: GET /foo HTTP/1.1
+ my-header: foo \n Config: add: - name: \"my-header\"
+ value: \"bar,baz\" \n Output: GET /foo HTTP/1.1
+ my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from
+ the HTTP request before the action. The value
+ of Remove is a list of HTTP header names.
+ Note that the header names are case-insensitive
+ (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo
+ my-header2: bar my-header3: baz \n Config:
+ remove: [\"my-header1\", \"my-header3\"] \n
+ Output: GET /foo HTTP/1.1 my-header2: bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with
+ the given header (name, value) before the
+ action. \n Input: GET /foo HTTP/1.1 my-header:
+ foo \n Config: set: - name: \"my-header\"
+ value: \"bar\" \n Output: GET /foo HTTP/1.1
+ my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ requestMirror:
+ description: "RequestMirror defines a schema for
+ a filter that mirrors requests. Requests are sent
+ to the specified destination, but responses from
+ that destination are ignored. \n This filter can
+ be used multiple times within the same rule. Note
+ that not all implementations will be able to support
+ mirroring to multiple backends. \n Support: Extended"
+ properties:
+ backendRef:
+ description: "BackendRef references a resource
+ where mirrored requests are sent. \n Mirrored
+ requests must be sent only to a single destination
+ endpoint within this BackendRef, irrespective
+ of how many endpoints are present within this
+ BackendRef. \n If the referent cannot be found,
+ this BackendRef is invalid and must be dropped
+ from the Gateway. The controller must ensure
+ the \"ResolvedRefs\" condition on the Route
+ status is set to `status: False` and not configure
+ this backend in the underlying implementation.
+ \n If there is a cross-namespace reference
+ to an *existing* object that is not allowed
+ by a ReferenceGrant, the controller must ensure
+ the \"ResolvedRefs\" condition on the Route
+ is set to `status: False`, with the \"RefNotPermitted\"
+ reason and not configure this backend in the
+ underlying implementation. \n In either error
+ case, the Message of the `ResolvedRefs` Condition
+ should be used to provide more detail about
+ the problem. \n Support: Extended for Kubernetes
+ Service \n Support: Implementation-specific
+ for any other resource"
+ properties:
+ group:
+ default: ""
+ description: Group is the group of the referent.
+ For example, "gateway.networking.k8s.io".
+ When unspecified or empty string, core
+ API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Service
+ description: "Kind is the Kubernetes resource
+ kind of the referent. For example \"Service\".
+ \n Defaults to \"Service\" when not specified.
+ \n ExternalName services can refer to
+ CNAME DNS records that may live outside
+ of the cluster and as such are difficult
+ to reason about in terms of conformance.
+ They also may not be safe to forward to
+ (see CVE-2021-25740 for more information).
+ Implementations SHOULD NOT support ExternalName
+ Services. \n Support: Core (Services with
+ a type other than ExternalName) \n Support:
+ Implementation-specific (Services with
+ type ExternalName)"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace
+ of the backend. When unspecified, the
+ local namespace is inferred. \n Note that
+ when a namespace different than the local
+ namespace is specified, a ReferenceGrant
+ object is required in the referent namespace
+ to allow that namespace's owner to accept
+ the reference. See the ReferenceGrant
+ documentation for details. \n Support:
+ Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ port:
+ description: Port specifies the destination
+ port number to use for this resource.
+ Port is required when the referent is
+ a Kubernetes Service. In this case, the
+ port number is the service port number,
+ not the target port. For other resources,
+ destination port might be derived from
+ the referent resource or this field.
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ required:
+ - name
+ type: object
+ x-kubernetes-validations:
+ - message: Must have port for Service reference
+ rule: '(size(self.group) == 0 && self.kind
+ == ''Service'') ? has(self.port) : true'
+ required:
+ - backendRef
+ type: object
+ requestRedirect:
+ description: "RequestRedirect defines a schema for
+ a filter that responds to the request with an
+ HTTP redirection. \n Support: Core"
+ properties:
+ hostname:
+ description: "Hostname is the hostname to be
+ used in the value of the `Location` header
+ in the response. When empty, the hostname
+ in the `Host` header of the request is used.
+ \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines parameters used to
+ modify the path of the incoming request. The
+ modified path is then used to construct the
+ `Location` header. When empty, the request
+ path is used as-is. \n Support: Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the
+ value with which to replace the full path
+ of a request during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies
+ the value with which to replace the prefix
+ match of a request during a rewrite or
+ redirect. For example, a request to \"/foo/bar\"
+ with a prefix match of \"/foo\" and a
+ ReplacePrefixMatch of \"/xyz\" would be
+ modified to \"/xyz/bar\". \n Note that
+ this matches the behavior of the PathPrefix
+ match type. This matches full path elements.
+ A path element refers to the list of labels
+ in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored.
+ For example, the paths `/abc`, `/abc/`,
+ and `/abc/def` would all match the prefix
+ `/abc`, but the path `/abcd` would not.
+ \n ReplacePrefixMatch is only compatible
+ with a `PathPrefix` HTTPRouteMatch. Using
+ any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`. \n Request Path
+ | Prefix Match | Replace Prefix | Modified
+ Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo |
+ /xyz/ | /xyz/bar /foo/bar |
+ /foo/ | /xyz | /xyz/bar
+ /foo/bar | /foo/ | /xyz/ |
+ /xyz/bar /foo | /foo |
+ /xyz | /xyz /foo/ | /foo
+ \ | /xyz | /xyz/ /foo/bar
+ \ | /foo | |
+ /bar /foo/ | /foo | | / /foo | /foo |
+ | / /foo/ | /foo
+ \ | / | / /foo |
+ /foo | / | /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path
+ modifier. Additional types may be added
+ in a future release of the API. \n Note
+ that values may be added to this enum,
+ implementations must ensure that unknown
+ values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`, with a Reason
+ of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified
+ when type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ?
+ has(self.replaceFullPath) : true'
+ - message: type must be 'ReplaceFullPath' when
+ replaceFullPath is set
+ rule: 'has(self.replaceFullPath) ? self.type
+ == ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified
+ when type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch''
+ ? has(self.replacePrefixMatch) : true'
+ - message: type must be 'ReplacePrefixMatch'
+ when replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ port:
+ description: "Port is the port to be used in
+ the value of the `Location` header in the
+ response. \n If no port is specified, the
+ redirect port MUST be derived using the following
+ rules: \n * If redirect scheme is not-empty,
+ the redirect port MUST be the well-known port
+ associated with the redirect scheme. Specifically
+ \"http\" to port 80 and \"https\" to port
+ 443. If the redirect scheme does not have
+ a well-known port, the listener port of the
+ Gateway SHOULD be used. * If redirect scheme
+ is empty, the redirect port MUST be the Gateway
+ Listener port. \n Implementations SHOULD NOT
+ add the port number in the 'Location' header
+ in the following cases: \n * A Location header
+ that will use HTTP (whether that is determined
+ via the Listener protocol or the Scheme field)
+ _and_ use port 80. * A Location header that
+ will use HTTPS (whether that is determined
+ via the Listener protocol or the Scheme field)
+ _and_ use port 443. \n Support: Extended"
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ scheme:
+ description: "Scheme is the scheme to be used
+ in the value of the `Location` header in the
+ response. When empty, the scheme of the request
+ is used. \n Scheme redirects can affect the
+ port of the redirect, for more information,
+ refer to the documentation for the port field
+ of this filter. \n Note that values may be
+ added to this enum, implementations must ensure
+ that unknown values will not cause a crash.
+ \n Unknown values here must result in the
+ implementation setting the Accepted Condition
+ for the Route to `status: False`, with a Reason
+ of `UnsupportedValue`. \n Support: Extended"
+ enum:
+ - http
+ - https
+ type: string
+ statusCode:
+ default: 302
+ description: "StatusCode is the HTTP status
+ code to be used in response. \n Note that
+ values may be added to this enum, implementations
+ must ensure that unknown values will not cause
+ a crash. \n Unknown values here must result
+ in the implementation setting the Accepted
+ Condition for the Route to `status: False`,
+ with a Reason of `UnsupportedValue`. \n Support:
+ Core"
+ enum:
+ - 301
+ - 302
+ type: integer
+ type: object
+ responseHeaderModifier:
+ description: "ResponseHeaderModifier defines a schema
+ for a filter that modifies response headers. \n
+ Support: Extended"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It
+ appends to any existing values associated
+ with the header name. \n Input: GET /foo HTTP/1.1
+ my-header: foo \n Config: add: - name: \"my-header\"
+ value: \"bar,baz\" \n Output: GET /foo HTTP/1.1
+ my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from
+ the HTTP request before the action. The value
+ of Remove is a list of HTTP header names.
+ Note that the header names are case-insensitive
+ (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo
+ my-header2: bar my-header3: baz \n Config:
+ remove: [\"my-header1\", \"my-header3\"] \n
+ Output: GET /foo HTTP/1.1 my-header2: bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with
+ the given header (name, value) before the
+ action. \n Input: GET /foo HTTP/1.1 my-header:
+ foo \n Config: set: - name: \"my-header\"
+ value: \"bar\" \n Output: GET /foo HTTP/1.1
+ my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP
+ Header name and value as defined by RFC
+ 7230.
+ properties:
+ name:
+ description: "Name is the name of the
+ HTTP Header to be matched. Name matching
+ MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an
+ equivalent name MUST be considered for
+ a match. Subsequent entries with an
+ equivalent header name MUST be ignored.
+ Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP
+ Header to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ type:
+ description: "Type identifies the type of filter
+ to apply. As with other API fields, types are
+ classified into three conformance levels: \n -
+ Core: Filter types and their corresponding configuration
+ defined by \"Support: Core\" in this package,
+ e.g. \"RequestHeaderModifier\". All implementations
+ must support core filters. \n - Extended: Filter
+ types and their corresponding configuration defined
+ by \"Support: Extended\" in this package, e.g.
+ \"RequestMirror\". Implementers are encouraged
+ to support extended filters. \n - Implementation-specific:
+ Filters that are defined and supported by specific
+ vendors. In the future, filters showing convergence
+ in behavior across multiple implementations will
+ be considered for inclusion in extended or core
+ conformance levels. Filter-specific configuration
+ for such filters is specified using the ExtensionRef
+ field. `Type` should be set to \"ExtensionRef\"
+ for custom filters. \n Implementers are encouraged
+ to define custom implementation types to extend
+ the core API with implementation-specific behavior.
+ \n If a reference to a custom filter type cannot
+ be resolved, the filter MUST NOT be skipped. Instead,
+ requests that would have been processed by that
+ filter MUST receive a HTTP error response. \n
+ Note that values may be added to this enum, implementations
+ must ensure that unknown values will not cause
+ a crash. \n Unknown values here must result in
+ the implementation setting the Accepted Condition
+ for the Route to `status: False`, with a Reason
+ of `UnsupportedValue`."
+ enum:
+ - RequestHeaderModifier
+ - ResponseHeaderModifier
+ - RequestMirror
+ - RequestRedirect
+ - URLRewrite
+ - ExtensionRef
+ type: string
+ urlRewrite:
+ description: "URLRewrite defines a schema for a
+ filter that modifies a request during forwarding.
+ \n Support: Extended"
+ properties:
+ hostname:
+ description: "Hostname is the value to be used
+ to replace the Host header value during forwarding.
+ \n Support: Extended"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines a path rewrite. \n
+ Support: Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the
+ value with which to replace the full path
+ of a request during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies
+ the value with which to replace the prefix
+ match of a request during a rewrite or
+ redirect. For example, a request to \"/foo/bar\"
+ with a prefix match of \"/foo\" and a
+ ReplacePrefixMatch of \"/xyz\" would be
+ modified to \"/xyz/bar\". \n Note that
+ this matches the behavior of the PathPrefix
+ match type. This matches full path elements.
+ A path element refers to the list of labels
+ in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored.
+ For example, the paths `/abc`, `/abc/`,
+ and `/abc/def` would all match the prefix
+ `/abc`, but the path `/abcd` would not.
+ \n ReplacePrefixMatch is only compatible
+ with a `PathPrefix` HTTPRouteMatch. Using
+ any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`. \n Request Path
+ | Prefix Match | Replace Prefix | Modified
+ Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo |
+ /xyz/ | /xyz/bar /foo/bar |
+ /foo/ | /xyz | /xyz/bar
+ /foo/bar | /foo/ | /xyz/ |
+ /xyz/bar /foo | /foo |
+ /xyz | /xyz /foo/ | /foo
+ \ | /xyz | /xyz/ /foo/bar
+ \ | /foo | |
+ /bar /foo/ | /foo | | / /foo | /foo |
+ | / /foo/ | /foo
+ \ | / | / /foo |
+ /foo | / | /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path
+ modifier. Additional types may be added
+ in a future release of the API. \n Note
+ that values may be added to this enum,
+ implementations must ensure that unknown
+ values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the
+ Route to `status: False`, with a Reason
+ of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified
+ when type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ?
+ has(self.replaceFullPath) : true'
+ - message: type must be 'ReplaceFullPath' when
+ replaceFullPath is set
+ rule: 'has(self.replaceFullPath) ? self.type
+ == ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified
+ when type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch''
+ ? has(self.replacePrefixMatch) : true'
+ - message: type must be 'ReplacePrefixMatch'
+ when replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ type: object
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: filter.requestHeaderModifier must be nil
+ if the filter.type is not RequestHeaderModifier
+ rule: '!(has(self.requestHeaderModifier) && self.type
+ != ''RequestHeaderModifier'')'
+ - message: filter.requestHeaderModifier must be specified
+ for RequestHeaderModifier filter.type
+ rule: '!(!has(self.requestHeaderModifier) && self.type
+ == ''RequestHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be nil
+ if the filter.type is not ResponseHeaderModifier
+ rule: '!(has(self.responseHeaderModifier) && self.type
+ != ''ResponseHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be specified
+ for ResponseHeaderModifier filter.type
+ rule: '!(!has(self.responseHeaderModifier) && self.type
+ == ''ResponseHeaderModifier'')'
+ - message: filter.requestMirror must be nil if the filter.type
+ is not RequestMirror
+ rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')'
+ - message: filter.requestMirror must be specified for
+ RequestMirror filter.type
+ rule: '!(!has(self.requestMirror) && self.type ==
+ ''RequestMirror'')'
+ - message: filter.requestRedirect must be nil if the
+ filter.type is not RequestRedirect
+ rule: '!(has(self.requestRedirect) && self.type !=
+ ''RequestRedirect'')'
+ - message: filter.requestRedirect must be specified
+ for RequestRedirect filter.type
+ rule: '!(!has(self.requestRedirect) && self.type ==
+ ''RequestRedirect'')'
+ - message: filter.urlRewrite must be nil if the filter.type
+ is not URLRewrite
+ rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')'
+ - message: filter.urlRewrite must be specified for URLRewrite
+ filter.type
+ rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')'
+ - message: filter.extensionRef must be nil if the filter.type
+ is not ExtensionRef
+ rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')'
+ - message: filter.extensionRef must be specified for
+ ExtensionRef filter.type
+ rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')'
+ maxItems: 16
+ type: array
+ x-kubernetes-validations:
+ - message: May specify either httpRouteFilterRequestRedirect
+ or httpRouteFilterRequestRewrite, but not both
+ rule: '!(self.exists(f, f.type == ''RequestRedirect'')
+ && self.exists(f, f.type == ''URLRewrite''))'
+ - message: May specify either httpRouteFilterRequestRedirect
+ or httpRouteFilterRequestRewrite, but not both
+ rule: '!(self.exists(f, f.type == ''RequestRedirect'')
+ && self.exists(f, f.type == ''URLRewrite''))'
+ - message: RequestHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestHeaderModifier').size()
+ <= 1
+ - message: ResponseHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'ResponseHeaderModifier').size()
+ <= 1
+ - message: RequestRedirect filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestRedirect').size()
+ <= 1
+ - message: URLRewrite filter cannot be repeated
+ rule: self.filter(f, f.type == 'URLRewrite').size()
+ <= 1
+ group:
+ default: ""
+ description: Group is the group of the referent. For example,
+ "gateway.networking.k8s.io". When unspecified or empty
+ string, core API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Service
+ description: "Kind is the Kubernetes resource kind of
+ the referent. For example \"Service\". \n Defaults to
+ \"Service\" when not specified. \n ExternalName services
+ can refer to CNAME DNS records that may live outside
+ of the cluster and as such are difficult to reason about
+ in terms of conformance. They also may not be safe to
+ forward to (see CVE-2021-25740 for more information).
+ Implementations SHOULD NOT support ExternalName Services.
+ \n Support: Core (Services with a type other than ExternalName)
+ \n Support: Implementation-specific (Services with type
+ ExternalName)"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the backend.
+ When unspecified, the local namespace is inferred. \n
+ Note that when a namespace different than the local
+ namespace is specified, a ReferenceGrant object is required
+ in the referent namespace to allow that namespace's
+ owner to accept the reference. See the ReferenceGrant
+ documentation for details. \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ port:
+ description: Port specifies the destination port number
+ to use for this resource. Port is required when the
+ referent is a Kubernetes Service. In this case, the
+ port number is the service port number, not the target
+ port. For other resources, destination port might be
+ derived from the referent resource or this field.
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ weight:
+ default: 1
+ description: "Weight specifies the proportion of requests
+ forwarded to the referenced backend. This is computed
+ as weight/(sum of all weights in this BackendRefs list).
+ For non-zero values, there may be some epsilon from
+ the exact proportion defined here depending on the precision
+ an implementation supports. Weight is not a percentage
+ and the sum of weights does not need to equal 100. \n
+ If only one backend is specified and it has a weight
+ greater than 0, 100% of the traffic is forwarded to
+ that backend. If weight is set to 0, no traffic should
+ be forwarded for this entry. If unspecified, weight
+ defaults to 1. \n Support for this field varies based
+ on the context where used."
+ format: int32
+ maximum: 1000000
+ minimum: 0
+ type: integer
+ required:
+ - name
+ type: object
+ x-kubernetes-validations:
+ - message: Must have port for Service reference
+ rule: '(size(self.group) == 0 && self.kind == ''Service'')
+ ? has(self.port) : true'
+ maxItems: 16
+ type: array
+ filters:
+ description: "Filters define the filters that are applied to
+ requests that match this rule. \n The effects of ordering
+ of multiple behaviors are currently unspecified. This can
+ change in the future based on feedback during the alpha stage.
+ \n Conformance-levels at this level are defined based on the
+ type of filter: \n - ALL core filters MUST be supported by
+ all implementations. - Implementers are encouraged to support
+ extended filters. - Implementation-specific custom filters
+ have no API guarantees across implementations. \n Specifying
+ the same filter multiple times is not supported unless explicitly
+ indicated in the filter. \n All filters are expected to be
+ compatible with each other except for the URLRewrite and RequestRedirect
+ filters, which may not be combined. If an implementation can
+ not support other combinations of filters, they must clearly
+ document that limitation. In cases where incompatible or unsupported
+ filters are specified and cause the `Accepted` condition to
+ be set to status `False`, implementations may use the `IncompatibleFilters`
+ reason to specify this configuration error. \n Support: Core"
+ items:
+ description: HTTPRouteFilter defines processing steps that
+ must be completed during the request or response lifecycle.
+ HTTPRouteFilters are meant as an extension point to express
+ processing that may be done in Gateway implementations.
+ Some examples include request or response modification,
+ implementing authentication strategies, rate-limiting, and
+ traffic shaping. API guarantee/conformance is defined based
+ on the type of the filter.
+ properties:
+ extensionRef:
+ description: "ExtensionRef is an optional, implementation-specific
+ extension to the \"filter\" behavior. For example,
+ resource \"myroutefilter\" in group \"networking.example.net\").
+ ExtensionRef MUST NOT be used for core and extended
+ filters. \n This filter can be used multiple times within
+ the same rule. \n Support: Implementation-specific"
+ properties:
+ group:
+ description: Group is the group of the referent. For
+ example, "gateway.networking.k8s.io". When unspecified
+ or empty string, core API group is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: Kind is kind of the referent. For example
+ "HTTPRoute" or "Service".
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - group
+ - kind
+ - name
+ type: object
+ requestHeaderModifier:
+ description: "RequestHeaderModifier defines a schema for
+ a filter that modifies request headers. \n Support:
+ Core"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It appends
+ to any existing values associated with the header
+ name. \n Input: GET /foo HTTP/1.1 my-header: foo
+ \n Config: add: - name: \"my-header\" value: \"bar,baz\"
+ \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from the
+ HTTP request before the action. The value of Remove
+ is a list of HTTP header names. Note that the header
+ names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2:
+ bar my-header3: baz \n Config: remove: [\"my-header1\",
+ \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2:
+ bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with the
+ given header (name, value) before the action. \n
+ Input: GET /foo HTTP/1.1 my-header: foo \n Config:
+ set: - name: \"my-header\" value: \"bar\" \n Output:
+ GET /foo HTTP/1.1 my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ requestMirror:
+ description: "RequestMirror defines a schema for a filter
+ that mirrors requests. Requests are sent to the specified
+ destination, but responses from that destination are
+ ignored. \n This filter can be used multiple times within
+ the same rule. Note that not all implementations will
+ be able to support mirroring to multiple backends. \n
+ Support: Extended"
+ properties:
+ backendRef:
+ description: "BackendRef references a resource where
+ mirrored requests are sent. \n Mirrored requests
+ must be sent only to a single destination endpoint
+ within this BackendRef, irrespective of how many
+ endpoints are present within this BackendRef. \n
+ If the referent cannot be found, this BackendRef
+ is invalid and must be dropped from the Gateway.
+ The controller must ensure the \"ResolvedRefs\"
+ condition on the Route status is set to `status:
+ False` and not configure this backend in the underlying
+ implementation. \n If there is a cross-namespace
+ reference to an *existing* object that is not allowed
+ by a ReferenceGrant, the controller must ensure
+ the \"ResolvedRefs\" condition on the Route is
+ set to `status: False`, with the \"RefNotPermitted\"
+ reason and not configure this backend in the underlying
+ implementation. \n In either error case, the Message
+ of the `ResolvedRefs` Condition should be used to
+ provide more detail about the problem. \n Support:
+ Extended for Kubernetes Service \n Support: Implementation-specific
+ for any other resource"
+ properties:
+ group:
+ default: ""
+ description: Group is the group of the referent.
+ For example, "gateway.networking.k8s.io". When
+ unspecified or empty string, core API group
+ is inferred.
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Service
+ description: "Kind is the Kubernetes resource
+ kind of the referent. For example \"Service\".
+ \n Defaults to \"Service\" when not specified.
+ \n ExternalName services can refer to CNAME
+ DNS records that may live outside of the cluster
+ and as such are difficult to reason about in
+ terms of conformance. They also may not be safe
+ to forward to (see CVE-2021-25740 for more information).
+ Implementations SHOULD NOT support ExternalName
+ Services. \n Support: Core (Services with a
+ type other than ExternalName) \n Support: Implementation-specific
+ (Services with type ExternalName)"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent.
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the
+ backend. When unspecified, the local namespace
+ is inferred. \n Note that when a namespace different
+ than the local namespace is specified, a ReferenceGrant
+ object is required in the referent namespace
+ to allow that namespace's owner to accept the
+ reference. See the ReferenceGrant documentation
+ for details. \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ port:
+ description: Port specifies the destination port
+ number to use for this resource. Port is required
+ when the referent is a Kubernetes Service. In
+ this case, the port number is the service port
+ number, not the target port. For other resources,
+ destination port might be derived from the referent
+ resource or this field.
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ required:
+ - name
+ type: object
+ x-kubernetes-validations:
+ - message: Must have port for Service reference
+ rule: '(size(self.group) == 0 && self.kind == ''Service'')
+ ? has(self.port) : true'
+ required:
+ - backendRef
+ type: object
+ requestRedirect:
+ description: "RequestRedirect defines a schema for a filter
+ that responds to the request with an HTTP redirection.
+ \n Support: Core"
+ properties:
+ hostname:
+ description: "Hostname is the hostname to be used
+ in the value of the `Location` header in the response.
+ When empty, the hostname in the `Host` header of
+ the request is used. \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines parameters used to modify
+ the path of the incoming request. The modified path
+ is then used to construct the `Location` header.
+ When empty, the request path is used as-is. \n Support:
+ Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the value
+ with which to replace the full path of a request
+ during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies the
+ value with which to replace the prefix match
+ of a request during a rewrite or redirect. For
+ example, a request to \"/foo/bar\" with a prefix
+ match of \"/foo\" and a ReplacePrefixMatch of
+ \"/xyz\" would be modified to \"/xyz/bar\".
+ \n Note that this matches the behavior of the
+ PathPrefix match type. This matches full path
+ elements. A path element refers to the list
+ of labels in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored. For
+ example, the paths `/abc`, `/abc/`, and `/abc/def`
+ would all match the prefix `/abc`, but the path
+ `/abcd` would not. \n ReplacePrefixMatch is
+ only compatible with a `PathPrefix` HTTPRouteMatch.
+ Using any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`. \n Request Path | Prefix
+ Match | Replace Prefix | Modified Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo | /xyz/
+ \ | /xyz/bar /foo/bar | /foo/ |
+ /xyz | /xyz/bar /foo/bar | /foo/
+ \ | /xyz/ | /xyz/bar /foo |
+ /foo | /xyz | /xyz /foo/ |
+ /foo | /xyz | /xyz/ /foo/bar
+ \ | /foo | | /bar
+ /foo/ | /foo |
+ | / /foo | /foo |
+ | / /foo/ | /foo | / |
+ / /foo | /foo | / |
+ /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path modifier.
+ Additional types may be added in a future release
+ of the API. \n Note that values may be added
+ to this enum, implementations must ensure that
+ unknown values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`, with a Reason of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified when
+ type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath)
+ : true'
+ - message: type must be 'ReplaceFullPath' when replaceFullPath
+ is set
+ rule: 'has(self.replaceFullPath) ? self.type ==
+ ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified when
+ type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch)
+ : true'
+ - message: type must be 'ReplacePrefixMatch' when
+ replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ port:
+ description: "Port is the port to be used in the value
+ of the `Location` header in the response. \n If
+ no port is specified, the redirect port MUST be
+ derived using the following rules: \n * If redirect
+ scheme is not-empty, the redirect port MUST be the
+ well-known port associated with the redirect scheme.
+ Specifically \"http\" to port 80 and \"https\" to
+ port 443. If the redirect scheme does not have a
+ well-known port, the listener port of the Gateway
+ SHOULD be used. * If redirect scheme is empty, the
+ redirect port MUST be the Gateway Listener port.
+ \n Implementations SHOULD NOT add the port number
+ in the 'Location' header in the following cases:
+ \n * A Location header that will use HTTP (whether
+ that is determined via the Listener protocol or
+ the Scheme field) _and_ use port 80. * A Location
+ header that will use HTTPS (whether that is determined
+ via the Listener protocol or the Scheme field) _and_
+ use port 443. \n Support: Extended"
+ format: int32
+ maximum: 65535
+ minimum: 1
+ type: integer
+ scheme:
+ description: "Scheme is the scheme to be used in the
+ value of the `Location` header in the response.
+ When empty, the scheme of the request is used. \n
+ Scheme redirects can affect the port of the redirect,
+ for more information, refer to the documentation
+ for the port field of this filter. \n Note that
+ values may be added to this enum, implementations
+ must ensure that unknown values will not cause a
+ crash. \n Unknown values here must result in the
+ implementation setting the Accepted Condition for
+ the Route to `status: False`, with a Reason of `UnsupportedValue`.
+ \n Support: Extended"
+ enum:
+ - http
+ - https
+ type: string
+ statusCode:
+ default: 302
+ description: "StatusCode is the HTTP status code to
+ be used in response. \n Note that values may be
+ added to this enum, implementations must ensure
+ that unknown values will not cause a crash. \n Unknown
+ values here must result in the implementation setting
+ the Accepted Condition for the Route to `status:
+ False`, with a Reason of `UnsupportedValue`. \n
+ Support: Core"
+ enum:
+ - 301
+ - 302
+ type: integer
+ type: object
+ responseHeaderModifier:
+ description: "ResponseHeaderModifier defines a schema
+ for a filter that modifies response headers. \n Support:
+ Extended"
+ properties:
+ add:
+ description: "Add adds the given header(s) (name,
+ value) to the request before the action. It appends
+ to any existing values associated with the header
+ name. \n Input: GET /foo HTTP/1.1 my-header: foo
+ \n Config: add: - name: \"my-header\" value: \"bar,baz\"
+ \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ remove:
+ description: "Remove the given header(s) from the
+ HTTP request before the action. The value of Remove
+ is a list of HTTP header names. Note that the header
+ names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
+ \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2:
+ bar my-header3: baz \n Config: remove: [\"my-header1\",
+ \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2:
+ bar"
+ items:
+ type: string
+ maxItems: 16
+ type: array
+ x-kubernetes-list-type: set
+ set:
+ description: "Set overwrites the request with the
+ given header (name, value) before the action. \n
+ Input: GET /foo HTTP/1.1 my-header: foo \n Config:
+ set: - name: \"my-header\" value: \"bar\" \n Output:
+ GET /foo HTTP/1.1 my-header: bar"
+ items:
+ description: HTTPHeader represents an HTTP Header
+ name and value as defined by RFC 7230.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case
+ insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent
+ header names, the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST
+ be ignored. Due to the case-insensitivity
+ of header names, \"foo\" and \"Foo\" are considered
+ equivalent."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ value:
+ description: Value is the value of HTTP Header
+ to be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ type:
+ description: "Type identifies the type of filter to apply.
+ As with other API fields, types are classified into
+ three conformance levels: \n - Core: Filter types and
+ their corresponding configuration defined by \"Support:
+ Core\" in this package, e.g. \"RequestHeaderModifier\".
+ All implementations must support core filters. \n -
+ Extended: Filter types and their corresponding configuration
+ defined by \"Support: Extended\" in this package, e.g.
+ \"RequestMirror\". Implementers are encouraged to support
+ extended filters. \n - Implementation-specific: Filters
+ that are defined and supported by specific vendors.
+ In the future, filters showing convergence in behavior
+ across multiple implementations will be considered for
+ inclusion in extended or core conformance levels. Filter-specific
+ configuration for such filters is specified using the
+ ExtensionRef field. `Type` should be set to \"ExtensionRef\"
+ for custom filters. \n Implementers are encouraged to
+ define custom implementation types to extend the core
+ API with implementation-specific behavior. \n If a reference
+ to a custom filter type cannot be resolved, the filter
+ MUST NOT be skipped. Instead, requests that would have
+ been processed by that filter MUST receive a HTTP error
+ response. \n Note that values may be added to this enum,
+ implementations must ensure that unknown values will
+ not cause a crash. \n Unknown values here must result
+ in the implementation setting the Accepted Condition
+ for the Route to `status: False`, with a Reason of `UnsupportedValue`."
+ enum:
+ - RequestHeaderModifier
+ - ResponseHeaderModifier
+ - RequestMirror
+ - RequestRedirect
+ - URLRewrite
+ - ExtensionRef
+ type: string
+ urlRewrite:
+ description: "URLRewrite defines a schema for a filter
+ that modifies a request during forwarding. \n Support:
+ Extended"
+ properties:
+ hostname:
+ description: "Hostname is the value to be used to
+ replace the Host header value during forwarding.
+ \n Support: Extended"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ path:
+ description: "Path defines a path rewrite. \n Support:
+ Extended"
+ properties:
+ replaceFullPath:
+ description: ReplaceFullPath specifies the value
+ with which to replace the full path of a request
+ during a rewrite or redirect.
+ maxLength: 1024
+ type: string
+ replacePrefixMatch:
+ description: "ReplacePrefixMatch specifies the
+ value with which to replace the prefix match
+ of a request during a rewrite or redirect. For
+ example, a request to \"/foo/bar\" with a prefix
+ match of \"/foo\" and a ReplacePrefixMatch of
+ \"/xyz\" would be modified to \"/xyz/bar\".
+ \n Note that this matches the behavior of the
+ PathPrefix match type. This matches full path
+ elements. A path element refers to the list
+ of labels in the path split by the `/` separator.
+ When specified, a trailing `/` is ignored. For
+ example, the paths `/abc`, `/abc/`, and `/abc/def`
+ would all match the prefix `/abc`, but the path
+ `/abcd` would not. \n ReplacePrefixMatch is
+ only compatible with a `PathPrefix` HTTPRouteMatch.
+ Using any other HTTPRouteMatch type on the same
+ HTTPRouteRule will result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`. \n Request Path | Prefix
+ Match | Replace Prefix | Modified Path -------------|--------------|----------------|----------
+ /foo/bar | /foo | /xyz |
+ /xyz/bar /foo/bar | /foo | /xyz/
+ \ | /xyz/bar /foo/bar | /foo/ |
+ /xyz | /xyz/bar /foo/bar | /foo/
+ \ | /xyz/ | /xyz/bar /foo |
+ /foo | /xyz | /xyz /foo/ |
+ /foo | /xyz | /xyz/ /foo/bar
+ \ | /foo | | /bar
+ /foo/ | /foo |
+ | / /foo | /foo |
+ | / /foo/ | /foo | / |
+ / /foo | /foo | / |
+ /"
+ maxLength: 1024
+ type: string
+ type:
+ description: "Type defines the type of path modifier.
+ Additional types may be added in a future release
+ of the API. \n Note that values may be added
+ to this enum, implementations must ensure that
+ unknown values will not cause a crash. \n Unknown
+ values here must result in the implementation
+ setting the Accepted Condition for the Route
+ to `status: False`, with a Reason of `UnsupportedValue`."
+ enum:
+ - ReplaceFullPath
+ - ReplacePrefixMatch
+ type: string
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: replaceFullPath must be specified when
+ type is set to 'ReplaceFullPath'
+ rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath)
+ : true'
+ - message: type must be 'ReplaceFullPath' when replaceFullPath
+ is set
+ rule: 'has(self.replaceFullPath) ? self.type ==
+ ''ReplaceFullPath'' : true'
+ - message: replacePrefixMatch must be specified when
+ type is set to 'ReplacePrefixMatch'
+ rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch)
+ : true'
+ - message: type must be 'ReplacePrefixMatch' when
+ replacePrefixMatch is set
+ rule: 'has(self.replacePrefixMatch) ? self.type
+ == ''ReplacePrefixMatch'' : true'
+ type: object
+ required:
+ - type
+ type: object
+ x-kubernetes-validations:
+ - message: filter.requestHeaderModifier must be nil if the
+ filter.type is not RequestHeaderModifier
+ rule: '!(has(self.requestHeaderModifier) && self.type !=
+ ''RequestHeaderModifier'')'
+ - message: filter.requestHeaderModifier must be specified
+ for RequestHeaderModifier filter.type
+ rule: '!(!has(self.requestHeaderModifier) && self.type ==
+ ''RequestHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be nil if the
+ filter.type is not ResponseHeaderModifier
+ rule: '!(has(self.responseHeaderModifier) && self.type !=
+ ''ResponseHeaderModifier'')'
+ - message: filter.responseHeaderModifier must be specified
+ for ResponseHeaderModifier filter.type
+ rule: '!(!has(self.responseHeaderModifier) && self.type
+ == ''ResponseHeaderModifier'')'
+ - message: filter.requestMirror must be nil if the filter.type
+ is not RequestMirror
+ rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')'
+ - message: filter.requestMirror must be specified for RequestMirror
+ filter.type
+ rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')'
+ - message: filter.requestRedirect must be nil if the filter.type
+ is not RequestRedirect
+ rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')'
+ - message: filter.requestRedirect must be specified for RequestRedirect
+ filter.type
+ rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')'
+ - message: filter.urlRewrite must be nil if the filter.type
+ is not URLRewrite
+ rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')'
+ - message: filter.urlRewrite must be specified for URLRewrite
+ filter.type
+ rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')'
+ - message: filter.extensionRef must be nil if the filter.type
+ is not ExtensionRef
+ rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')'
+ - message: filter.extensionRef must be specified for ExtensionRef
+ filter.type
+ rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')'
+ maxItems: 16
+ type: array
+ x-kubernetes-validations:
+ - message: May specify either httpRouteFilterRequestRedirect
+ or httpRouteFilterRequestRewrite, but not both
+ rule: '!(self.exists(f, f.type == ''RequestRedirect'') &&
+ self.exists(f, f.type == ''URLRewrite''))'
+ - message: RequestHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestHeaderModifier').size()
+ <= 1
+ - message: ResponseHeaderModifier filter cannot be repeated
+ rule: self.filter(f, f.type == 'ResponseHeaderModifier').size()
+ <= 1
+ - message: RequestRedirect filter cannot be repeated
+ rule: self.filter(f, f.type == 'RequestRedirect').size() <=
+ 1
+ - message: URLRewrite filter cannot be repeated
+ rule: self.filter(f, f.type == 'URLRewrite').size() <= 1
+ matches:
+ default:
+ - path:
+ type: PathPrefix
+ value: /
+ description: "Matches define conditions used for matching the
+ rule against incoming HTTP requests. Each match is independent,
+ i.e. this rule will be matched if **any** one of the matches
+ is satisfied. \n For example, take the following matches configuration:
+ \n ``` matches: - path: value: \"/foo\" headers: - name: \"version\"
+ value: \"v2\" - path: value: \"/v2/foo\" ``` \n For a request
+ to match against this rule, a request must satisfy EITHER
+ of the two conditions: \n - path prefixed with `/foo` AND
+ contains the header `version: v2` - path prefix of `/v2/foo`
+ \n See the documentation for HTTPRouteMatch on how to specify
+ multiple match conditions that should be ANDed together. \n
+ If no matches are specified, the default is a prefix path
+ match on \"/\", which has the effect of matching every HTTP
+ request. \n Proxy or Load Balancer routing configuration generated
+ from HTTPRoutes MUST prioritize matches based on the following
+ criteria, continuing on ties. Across all rules specified on
+ applicable Routes, precedence must be given to the match having:
+ \n * \"Exact\" path match. * \"Prefix\" path match with largest
+ number of characters. * Method match. * Largest number of
+ header matches. * Largest number of query param matches. \n
+ Note: The precedence of RegularExpression path matches are
+ implementation-specific. \n If ties still exist across multiple
+ Routes, matching precedence MUST be determined in order of
+ the following criteria, continuing on ties: \n * The oldest
+ Route based on creation timestamp. * The Route appearing first
+ in alphabetical order by \"{namespace}/{name}\". \n If ties
+ still exist within an HTTPRoute, matching precedence MUST
+ be granted to the FIRST matching rule (in list order) with
+ a match meeting the above criteria. \n When no rules matching
+ a request have been successfully attached to the parent a
+ request is coming from, a HTTP 404 status code MUST be returned."
+ items:
+ description: "HTTPRouteMatch defines the predicate used to
+ match requests to a given action. Multiple match types are
+ ANDed together, i.e. the match will evaluate to true only
+ if all conditions are satisfied. \n For example, the match
+ below will match a HTTP request only if its path starts
+ with `/foo` AND it contains the `version: v1` header: \n
+ ``` match: \n path: value: \"/foo\" headers: - name: \"version\"
+ value \"v1\" \n ```"
+ properties:
+ headers:
+ description: Headers specifies HTTP request header matchers.
+ Multiple match values are ANDed together, meaning, a
+ request must match all the specified headers to select
+ the route.
+ items:
+ description: HTTPHeaderMatch describes how to select
+ a HTTP route by matching HTTP request headers.
+ properties:
+ name:
+ description: "Name is the name of the HTTP Header
+ to be matched. Name matching MUST be case insensitive.
+ (See https://tools.ietf.org/html/rfc7230#section-3.2).
+ \n If multiple entries specify equivalent header
+ names, only the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent header name MUST be
+ ignored. Due to the case-insensitivity of header
+ names, \"foo\" and \"Foo\" are considered equivalent.
+ \n When a header is repeated in an HTTP request,
+ it is implementation-specific behavior as to how
+ this is represented. Generally, proxies should
+ follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2
+ regarding processing a repeated header, with special
+ handling for \"Set-Cookie\"."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ type:
+ default: Exact
+ description: "Type specifies how to match against
+ the value of the header. \n Support: Core (Exact)
+ \n Support: Implementation-specific (RegularExpression)
+ \n Since RegularExpression HeaderMatchType has
+ implementation-specific conformance, implementations
+ can support POSIX, PCRE or any other dialects
+ of regular expressions. Please read the implementation's
+ documentation to determine the supported dialect."
+ enum:
+ - Exact
+ - RegularExpression
+ type: string
+ value:
+ description: Value is the value of HTTP Header to
+ be matched.
+ maxLength: 4096
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ method:
+ description: "Method specifies HTTP method matcher. When
+ specified, this route will be matched only if the request
+ has the specified method. \n Support: Extended"
+ enum:
+ - GET
+ - HEAD
+ - POST
+ - PUT
+ - DELETE
+ - CONNECT
+ - OPTIONS
+ - TRACE
+ - PATCH
+ type: string
+ path:
+ default:
+ type: PathPrefix
+ value: /
+ description: Path specifies a HTTP request path matcher.
+ If this field is not specified, a default prefix match
+ on the "/" path is provided.
+ properties:
+ type:
+ default: PathPrefix
+ description: "Type specifies how to match against
+ the path Value. \n Support: Core (Exact, PathPrefix)
+ \n Support: Implementation-specific (RegularExpression)"
+ enum:
+ - Exact
+ - PathPrefix
+ - RegularExpression
+ type: string
+ value:
+ default: /
+ description: Value of the HTTP path to match against.
+ maxLength: 1024
+ type: string
+ type: object
+ x-kubernetes-validations:
+ - message: value must be an absolute path and start with
+ '/' when type one of ['Exact', 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'')
+ : true'
+ - message: must not contain '//' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'')
+ : true'
+ - message: must not contain '/./' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'')
+ : true'
+ - message: must not contain '/../' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'')
+ : true'
+ - message: must not contain '%2f' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'')
+ : true'
+ - message: must not contain '%2F' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'')
+ : true'
+ - message: must not contain '#' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'')
+ : true'
+ - message: must not end with '/..' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'')
+ : true'
+ - message: must not end with '/.' when type one of ['Exact',
+ 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'')
+ : true'
+ - message: type must be one of ['Exact', 'PathPrefix',
+ 'RegularExpression']
+ rule: self.type in ['Exact','PathPrefix'] || self.type
+ == 'RegularExpression'
+ - message: must only contain valid characters (matching
+ ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$)
+ for types ['Exact', 'PathPrefix']
+ rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""")
+ : true'
+ queryParams:
+ description: "QueryParams specifies HTTP query parameter
+ matchers. Multiple match values are ANDed together,
+ meaning, a request must match all the specified query
+ parameters to select the route. \n Support: Extended"
+ items:
+ description: HTTPQueryParamMatch describes how to select
+ a HTTP route by matching HTTP query parameters.
+ properties:
+ name:
+ description: "Name is the name of the HTTP query
+ param to be matched. This must be an exact string
+ match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3).
+ \n If multiple entries specify equivalent query
+ param names, only the first entry with an equivalent
+ name MUST be considered for a match. Subsequent
+ entries with an equivalent query param name MUST
+ be ignored. \n If a query param is repeated in
+ an HTTP request, the behavior is purposely left
+ undefined, since different data planes have different
+ capabilities. However, it is *recommended* that
+ implementations should match against the first
+ value of the param if the data plane supports
+ it, as this behavior is expected in other load
+ balancing contexts outside of the Gateway API.
+ \n Users SHOULD NOT route traffic based on repeated
+ query params to guard themselves against potential
+ differences in the implementations."
+ maxLength: 256
+ minLength: 1
+ pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$
+ type: string
+ type:
+ default: Exact
+ description: "Type specifies how to match against
+ the value of the query parameter. \n Support:
+ Extended (Exact) \n Support: Implementation-specific
+ (RegularExpression) \n Since RegularExpression
+ QueryParamMatchType has Implementation-specific
+ conformance, implementations can support POSIX,
+ PCRE or any other dialects of regular expressions.
+ Please read the implementation's documentation
+ to determine the supported dialect."
+ enum:
+ - Exact
+ - RegularExpression
+ type: string
+ value:
+ description: Value is the value of HTTP query param
+ to be matched.
+ maxLength: 1024
+ minLength: 1
+ type: string
+ required:
+ - name
+ - value
+ type: object
+ maxItems: 16
+ type: array
+ x-kubernetes-list-map-keys:
+ - name
+ x-kubernetes-list-type: map
+ type: object
+ maxItems: 8
+ type: array
+ type: object
+ x-kubernetes-validations:
+ - message: RequestRedirect filter must not be used together with
+ backendRefs
+ rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ?
+ (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))):
+ true'
+ - message: When using RequestRedirect filter with path.replacePrefixMatch,
+ exactly one PathPrefix match must be specified
+ rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect)
+ && has(f.requestRedirect.path) && f.requestRedirect.path.type
+ == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch)))
+ ? ((size(self.matches) != 1 || !has(self.matches[0].path) ||
+ self.matches[0].path.type != ''PathPrefix'') ? false : true)
+ : true'
+ - message: When using URLRewrite filter with path.replacePrefixMatch,
+ exactly one PathPrefix match must be specified
+ rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite)
+ && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch''
+ && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches)
+ != 1 || !has(self.matches[0].path) || self.matches[0].path.type
+ != ''PathPrefix'') ? false : true) : true'
+ - message: Within backendRefs, when using RequestRedirect filter
+ with path.replacePrefixMatch, exactly one PathPrefix match must
+ be specified
+ rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b,
+ (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect)
+ && has(f.requestRedirect.path) && f.requestRedirect.path.type
+ == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch)))
+ )) ? ((size(self.matches) != 1 || !has(self.matches[0].path)
+ || self.matches[0].path.type != ''PathPrefix'') ? false : true)
+ : true'
+ - message: Within backendRefs, When using URLRewrite filter with
+ path.replacePrefixMatch, exactly one PathPrefix match must be
+ specified
+ rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b,
+ (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite)
+ && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch''
+ && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches)
+ != 1 || !has(self.matches[0].path) || self.matches[0].path.type
+ != ''PathPrefix'') ? false : true) : true'
+ maxItems: 16
+ type: array
+ type: object
+ status:
+ description: Status defines the current state of HTTPRoute.
+ properties:
+ parents:
+ description: "Parents is a list of parent resources (usually Gateways)
+ that are associated with the route, and the status of the route
+ with respect to each parent. When this route attaches to a parent,
+ the controller that manages the parent must add an entry to this
+ list when the controller first sees the route and should update
+ the entry as appropriate when the route or gateway is modified.
+ \n Note that parent references that cannot be resolved by an implementation
+ of this API will not be added to this list. Implementations of this
+ API can only populate Route status for the Gateways/parent resources
+ they are responsible for. \n A maximum of 32 Gateways will be represented
+ in this list. An empty list means the route has not been attached
+ to any Gateway."
+ items:
+ description: RouteParentStatus describes the status of a route with
+ respect to an associated Parent.
+ properties:
+ conditions:
+ description: "Conditions describes the status of the route with
+ respect to the Gateway. Note that the route's availability
+ is also subject to the Gateway's own status conditions and
+ listener status. \n If the Route's ParentRef specifies an
+ existing Gateway that supports Routes of this kind AND that
+ Gateway's controller has sufficient access, then that Gateway's
+ controller MUST set the \"Accepted\" condition on the Route,
+ to indicate whether the route has been accepted or rejected
+ by the Gateway, and why. \n A Route MUST be considered \"Accepted\"
+ if at least one of the Route's rules is implemented by the
+ Gateway. \n There are a number of cases where the \"Accepted\"
+ condition may not be set due to lack of controller visibility,
+ that includes when: \n * The Route refers to a non-existent
+ parent. * The Route is of a type that the controller does
+ not support. * The Route is in a namespace the controller
+ does not have access to."
+ items:
+ description: "Condition contains details for one aspect of
+ the current state of this API Resource. --- This struct
+ is intended for direct use as an array at the field path
+ .status.conditions. For example, \n type FooStatus struct{
+ // Represents the observations of a foo's current state.
+ // Known .status.conditions.type are: \"Available\", \"Progressing\",
+ and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
+ // +listType=map // +listMapKey=type Conditions []metav1.Condition
+ `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
+ protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields
+ }"
+ properties:
+ lastTransitionTime:
+ description: lastTransitionTime is the last time the condition
+ transitioned from one status to another. This should
+ be when the underlying condition changed. If that is
+ not known, then using the time when the API field changed
+ is acceptable.
+ format: date-time
+ type: string
+ message:
+ description: message is a human readable message indicating
+ details about the transition. This may be an empty string.
+ maxLength: 32768
+ type: string
+ observedGeneration:
+ description: observedGeneration represents the .metadata.generation
+ that the condition was set based upon. For instance,
+ if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration
+ is 9, the condition is out of date with respect to the
+ current state of the instance.
+ format: int64
+ minimum: 0
+ type: integer
+ reason:
+ description: reason contains a programmatic identifier
+ indicating the reason for the condition's last transition.
+ Producers of specific condition types may define expected
+ values and meanings for this field, and whether the
+ values are considered a guaranteed API. The value should
+ be a CamelCase string. This field may not be empty.
+ maxLength: 1024
+ minLength: 1
+ pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
+ type: string
+ status:
+ description: status of the condition, one of True, False,
+ Unknown.
+ enum:
+ - "True"
+ - "False"
+ - Unknown
+ type: string
+ type:
+ description: type of condition in CamelCase or in foo.example.com/CamelCase.
+ --- Many .condition.type values are consistent across
+ resources like Available, but because arbitrary conditions
+ can be useful (see .node.status.conditions), the ability
+ to deconflict is important. The regex it matches is
+ (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+ maxLength: 316
+ pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
+ type: string
+ required:
+ - lastTransitionTime
+ - message
+ - reason
+ - status
+ - type
+ type: object
+ maxItems: 8
+ minItems: 1
+ type: array
+ x-kubernetes-list-map-keys:
+ - type
+ x-kubernetes-list-type: map
+ controllerName:
+ description: "ControllerName is a domain/path string that indicates
+ the name of the controller that wrote this status. This corresponds
+ with the controllerName field on GatewayClass. \n Example:
+ \"example.net/gateway-controller\". \n The format of this
+ field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid
+ Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
+ \n Controllers MUST populate this field when writing status.
+ Controllers should ensure that entries to status populated
+ with their ControllerName are cleaned up when they are no
+ longer necessary."
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$
+ type: string
+ parentRef:
+ description: ParentRef corresponds with a ParentRef in the spec
+ that this RouteParentStatus struct describes the status of.
+ properties:
+ group:
+ default: gateway.networking.k8s.io
+ description: "Group is the group of the referent. When unspecified,
+ \"gateway.networking.k8s.io\" is inferred. To set the
+ core API group (such as for a \"Service\" kind referent),
+ Group must be explicitly set to \"\" (empty string). \n
+ Support: Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ default: Gateway
+ description: "Kind is kind of the referent. \n There are
+ two kinds of parent resources with \"Core\" support: \n
+ * Gateway (Gateway conformance profile) * Service (Mesh
+ conformance profile, experimental, ClusterIP Services
+ only) \n Support for other resources is Implementation-Specific."
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: "Name is the name of the referent. \n Support:
+ Core"
+ maxLength: 253
+ minLength: 1
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referent.
+ When unspecified, this refers to the local namespace of
+ the Route. \n Note that there are specific rules for ParentRefs
+ which cross namespace boundaries. Cross-namespace references
+ are only valid if they are explicitly allowed by something
+ in the namespace they are referring to. For example: Gateway
+ has the AllowedRoutes field, and ReferenceGrant provides
+ a generic way to enable any other kind of cross-namespace
+ reference. \n \n Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ sectionName:
+ description: "SectionName is the name of a section within
+ the target resource. In the following resources, SectionName
+ is interpreted as the following: \n * Gateway: Listener
+ Name. When both Port (experimental) and SectionName are
+ specified, the name and port of the selected listener
+ must match both specified values. * Service: Port Name.
+ When both Port (experimental) and SectionName are specified,
+ the name and port of the selected listener must match
+ both specified values. Note that attaching Routes to Services
+ as Parents is part of experimental Mesh support and is
+ not supported for any other purpose. \n Implementations
+ MAY choose to support attaching Routes to other resources.
+ If that is the case, they MUST clearly document how SectionName
+ is interpreted. \n When unspecified (empty string), this
+ will reference the entire resource. For the purpose of
+ status, an attachment is considered successful if at least
+ one section in the parent resource accepts it. For example,
+ Gateway listeners can restrict which Routes can attach
+ to them by Route kind, namespace, or hostname. If 1 of
+ 2 Gateway listeners accept attachment from the referencing
+ Route, the Route MUST be considered successfully attached.
+ If no Gateway listeners accept attachment from this Route,
+ the Route MUST be considered detached from the Gateway.
+ \n Support: Core"
+ maxLength: 253
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ required:
+ - name
+ type: object
+ required:
+ - controllerName
+ - parentRef
+ type: object
+ maxItems: 32
+ type: array
+ required:
+ - parents
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+status:
+ acceptedNames:
+ kind: ""
+ plural: ""
+ conditions: null
+ storedVersions: null
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466
+ gateway.networking.k8s.io/bundle-version: v1.0.0
+ gateway.networking.k8s.io/channel: standard
+ creationTimestamp: null
+ name: referencegrants.gateway.networking.k8s.io
+spec:
+ group: gateway.networking.k8s.io
+ names:
+ categories:
+ - gateway-api
+ kind: ReferenceGrant
+ listKind: ReferenceGrantList
+ plural: referencegrants
+ shortNames:
+ - refgrant
+ singular: referencegrant
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ deprecated: true
+ deprecationWarning: The v1alpha2 version of ReferenceGrant has been deprecated
+ and will be removed in a future release of the API. Please upgrade to v1beta1.
+ name: v1alpha2
+ schema:
+ openAPIV3Schema:
+ description: "ReferenceGrant identifies kinds of resources in other namespaces
+ that are trusted to reference the specified kinds of resources in the same
+ namespace as the policy. \n Each ReferenceGrant can be used to represent
+ a unique trust relationship. Additional Reference Grants can be used to
+ add to the set of trusted sources of inbound references for the namespace
+ they are defined within. \n A ReferenceGrant is required for all cross-namespace
+ references in Gateway API (with the exception of cross-namespace Route-Gateway
+ attachment, which is governed by the AllowedRoutes configuration on the
+ Gateway, and cross-namespace Service ParentRefs on a \"consumer\" mesh Route,
+ which defines routing rules applicable only to workloads in the Route namespace).
+ ReferenceGrants allowing a reference from a Route to a Service are only
+ applicable to BackendRefs. \n ReferenceGrant is a form of runtime verification
+ allowing users to assert which cross-namespace object references are permitted.
+ Implementations that support ReferenceGrant MUST NOT permit cross-namespace
+ references which have no grant, and MUST respond to the removal of a grant
+ by revoking the access that the grant allowed."
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of ReferenceGrant.
+ properties:
+ from:
+ description: "From describes the trusted namespaces and kinds that
+ can reference the resources described in \"To\". Each entry in this
+ list MUST be considered to be an additional place that references
+ can be valid from, or to put this another way, entries MUST be combined
+ using OR. \n Support: Core"
+ items:
+ description: ReferenceGrantFrom describes trusted namespaces and
+ kinds.
+ properties:
+ group:
+ description: "Group is the group of the referent. When empty,
+ the Kubernetes core API group is inferred. \n Support: Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: "Kind is the kind of the referent. Although implementations
+ may support additional resources, the following types are
+ part of the \"Core\" support level for this field. \n When
+ used to permit a SecretObjectReference: \n * Gateway \n When
+ used to permit a BackendObjectReference: \n * GRPCRoute *
+ HTTPRoute * TCPRoute * TLSRoute * UDPRoute"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referent. \n
+ Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ required:
+ - group
+ - kind
+ - namespace
+ type: object
+ maxItems: 16
+ minItems: 1
+ type: array
+ to:
+ description: "To describes the resources that may be referenced by
+ the resources described in \"From\". Each entry in this list MUST
+ be considered to be an additional place that references can be valid
+ to, or to put this another way, entries MUST be combined using OR.
+ \n Support: Core"
+ items:
+ description: ReferenceGrantTo describes what Kinds are allowed as
+ targets of the references.
+ properties:
+ group:
+ description: "Group is the group of the referent. When empty,
+ the Kubernetes core API group is inferred. \n Support: Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: "Kind is the kind of the referent. Although implementations
+ may support additional resources, the following types are
+ part of the \"Core\" support level for this field: \n * Secret
+ when used to permit a SecretObjectReference * Service when
+ used to permit a BackendObjectReference"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent. When unspecified,
+ this policy refers to all resources of the specified Group
+ and Kind in the local namespace.
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - group
+ - kind
+ type: object
+ maxItems: 16
+ minItems: 1
+ type: array
+ required:
+ - from
+ - to
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources: {}
+ - additionalPrinterColumns:
+ - jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1beta1
+ schema:
+ openAPIV3Schema:
+ description: "ReferenceGrant identifies kinds of resources in other namespaces
+ that are trusted to reference the specified kinds of resources in the same
+ namespace as the policy. \n Each ReferenceGrant can be used to represent
+ a unique trust relationship. Additional Reference Grants can be used to
+ add to the set of trusted sources of inbound references for the namespace
+ they are defined within. \n All cross-namespace references in Gateway API
+ (with the exception of cross-namespace Gateway-route attachment) require
+ a ReferenceGrant. \n ReferenceGrant is a form of runtime verification allowing
+ users to assert which cross-namespace object references are permitted. Implementations
+ that support ReferenceGrant MUST NOT permit cross-namespace references which
+ have no grant, and MUST respond to the removal of a grant by revoking the
+ access that the grant allowed."
+ properties:
+ apiVersion:
+ description: 'APIVersion defines the versioned schema of this representation
+ of an object. Servers should convert recognized schemas to the latest
+ internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+ type: string
+ kind:
+ description: 'Kind is a string value representing the REST resource this
+ object represents. Servers may infer this from the endpoint the client
+ submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: Spec defines the desired state of ReferenceGrant.
+ properties:
+ from:
+ description: "From describes the trusted namespaces and kinds that
+ can reference the resources described in \"To\". Each entry in this
+ list MUST be considered to be an additional place that references
+ can be valid from, or to put this another way, entries MUST be combined
+ using OR. \n Support: Core"
+ items:
+ description: ReferenceGrantFrom describes trusted namespaces and
+ kinds.
+ properties:
+ group:
+ description: "Group is the group of the referent. When empty,
+ the Kubernetes core API group is inferred. \n Support: Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: "Kind is the kind of the referent. Although implementations
+ may support additional resources, the following types are
+ part of the \"Core\" support level for this field. \n When
+ used to permit a SecretObjectReference: \n * Gateway \n When
+ used to permit a BackendObjectReference: \n * GRPCRoute *
+ HTTPRoute * TCPRoute * TLSRoute * UDPRoute"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ namespace:
+ description: "Namespace is the namespace of the referent. \n
+ Support: Core"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+ type: string
+ required:
+ - group
+ - kind
+ - namespace
+ type: object
+ maxItems: 16
+ minItems: 1
+ type: array
+ to:
+ description: "To describes the resources that may be referenced by
+ the resources described in \"From\". Each entry in this list MUST
+ be considered to be an additional place that references can be valid
+ to, or to put this another way, entries MUST be combined using OR.
+ \n Support: Core"
+ items:
+ description: ReferenceGrantTo describes what Kinds are allowed as
+ targets of the references.
+ properties:
+ group:
+ description: "Group is the group of the referent. When empty,
+ the Kubernetes core API group is inferred. \n Support: Core"
+ maxLength: 253
+ pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+ type: string
+ kind:
+ description: "Kind is the kind of the referent. Although implementations
+ may support additional resources, the following types are
+ part of the \"Core\" support level for this field: \n * Secret
+ when used to permit a SecretObjectReference * Service when
+ used to permit a BackendObjectReference"
+ maxLength: 63
+ minLength: 1
+ pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+ type: string
+ name:
+ description: Name is the name of the referent. When unspecified,
+ this policy refers to all resources of the specified Group
+ and Kind in the local namespace.
+ maxLength: 253
+ minLength: 1
+ type: string
+ required:
+ - group
+ - kind
+ type: object
+ maxItems: 16
+ minItems: 1
+ type: array
+ required:
+ - from
+ - to
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources: {}
+status:
+ acceptedNames:
+ kind: ""
+ plural: ""
+ conditions: null
+ storedVersions: null
diff --git a/kong2kic/testdata/global-plugin-input.yaml b/kong2kic/testdata/global-plugin-input.yaml
new file mode 100644
index 000000000..d12209c0e
--- /dev/null
+++ b/kong2kic/testdata/global-plugin-input.yaml
@@ -0,0 +1,12 @@
+plugins:
+- name: prometheus
+ enabled: true
+ config:
+ per_consumer: true
+ status_code_metrics: true
+ latency_metrics: true
+ bandwidth_metrics: true
+ upstream_health_metrics: true
+ tags:
+ - cloudops-managed
+ - metrics
\ No newline at end of file
diff --git a/kong2kic/testdata/global-plugin-output-expected.yaml b/kong2kic/testdata/global-plugin-output-expected.yaml
new file mode 100644
index 000000000..2ecdc5fb1
--- /dev/null
+++ b/kong2kic/testdata/global-plugin-output-expected.yaml
@@ -0,0 +1,15 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ bandwidth_metrics: true
+ latency_metrics: true
+ per_consumer: true
+ status_code_metrics: true
+ upstream_health_metrics: true
+kind: KongClusterPlugin
+metadata:
+ annotations:
+ konghq.com/tags: cloudops-managed,metrics
+ kubernetes.io/ingress.class: kong
+ name: prometheus
+plugin: prometheus
+---
\ No newline at end of file
diff --git a/kong2kic/testdata/kicv2_gateway/output-expected.json b/kong2kic/testdata/kicv2_gateway/output-expected.json
deleted file mode 100644
index f18d118f2..000000000
--- a/kong2kic/testdata/kicv2_gateway/output-expected.json
+++ /dev/null
@@ -1,1483 +0,0 @@
-{
- "apiVersion": "configuration.konghq.com/v1",
- "kind": "KongIngress",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service-upstream"
- },
- "upstream": {
- "algorithm": "round-robin",
- "hash_fallback": "none",
- "hash_on": "none",
- "hash_on_cookie_path": "/",
- "healthchecks": {
- "active": {
- "concurrency": 10,
- "headers": {
- "x-another-header": [
- "bla"
- ],
- "x-my-header": [
- "foo",
- "bar"
- ]
- },
- "healthy": {
- "http_statuses": [
- 200,
- 302
- ],
- "interval": 0,
- "successes": 0
- },
- "http_path": "/",
- "https_sni": "example.com",
- "https_verify_certificate": true,
- "timeout": 1,
- "type": "http",
- "unhealthy": {
- "http_failures": 0,
- "http_statuses": [
- 429,
- 404,
- 500,
- 501,
- 502,
- 503,
- 504,
- 505
- ],
- "interval": 0,
- "tcp_failures": 0,
- "timeouts": 0
- }
- },
- "passive": {
- "healthy": {
- "http_statuses": [
- 200,
- 201,
- 202,
- 203,
- 204,
- 205,
- 206,
- 207,
- 208,
- 226,
- 300,
- 301,
- 302,
- 303,
- 304,
- 305,
- 306,
- 307,
- 308
- ],
- "successes": 0
- },
- "type": "http",
- "unhealthy": {
- "http_failures": 0,
- "http_statuses": [
- 429,
- 500,
- 503
- ],
- "tcp_failures": 0,
- "timeouts": 0
- }
- },
- "threshold": 0
- },
- "host_header": "example.com",
- "slots": 10000
- }
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "aws_key": "my_key",
- "aws_region": "us-west-2",
- "aws_secret": "my_secret",
- "function_name": "my_function"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "plugin": "aws-lambda"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "credentials": true,
- "exposed_headers": [
- "X-My-Header"
- ],
- "headers": [
- "Authorization"
- ],
- "max_age": 3600,
- "methods": [
- "GET",
- "POST"
- ],
- "origins": [
- "example.com"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "plugin": "cors"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "path": "/var/log/kong/kong.log",
- "reopen": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "plugin": "file-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "content_type": "application/json",
- "http_endpoint": "http://example.com/logs",
- "keepalive": 60000,
- "method": "POST",
- "queue_size": 1000,
- "retry_count": 10,
- "timeout": 10000
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "plugin": "http-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "192.168.0.1/24"
- ],
- "deny": [
- "192.168.0.2/32"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "plugin": "ip-restriction"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "message": "Forbidden",
- "status_code": 403
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "plugin": "request-termination"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "limits": {
- "limit_name": {
- "minute": 10
- }
- },
- "policy": "local"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "plugin": "response-ratelimiting"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "host": "example.com",
- "port": 1234
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "plugin": "tcp-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "plugin": "basic-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "anonymous": null,
- "claims_to_verify": [
- "exp",
- "nbf"
- ],
- "header_names": [
- "Authorization"
- ],
- "key_claim_name": "kid",
- "maximum_expiration": 3600,
- "run_on_preflight": true,
- "secret_is_base64": false,
- "uri_param_names": [
- "token"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "plugin": "jwt"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false,
- "key_in_body": false,
- "key_names": [
- "apikey"
- ],
- "run_on_preflight": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "plugin": "key-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "ca_certificates": [
- "cce8c384-721f-4f58-85dd-50834e3e733a"
- ],
- "revocation_check_mode": "SKIP",
- "skip_consumer_lookup": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "plugin": "mtls-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "admin"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "plugin": "acl"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "gateway.networking.k8s.io/v1beta1",
- "kind": "HTTPRoute",
- "metadata": {
- "annotations": {
- "konghq.com/https-redirect-status-code": "302",
- "konghq.com/preserve-host": "true",
- "konghq.com/regex-priority": "1",
- "konghq.com/snis": "example.com",
- "konghq.com/strip-path": "false"
- },
- "name": "example-service--route-thisisaveryvery-long2093a020ca"
- },
- "spec": {
- "hostnames": [
- "example.com",
- "another-example.com",
- "yet-another-example.com"
- ],
- "parentRefs": [
- {
- "name": "kong"
- }
- ],
- "rules": [
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "GET",
- "path": {
- "type": "RegularExpression",
- "value": "/v1/example/?$"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "POST",
- "path": {
- "type": "RegularExpression",
- "value": "/v1/example/?$"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "GET",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/another-example"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "POST",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/another-example"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "GET",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/yet-another-example"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "POST",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/yet-another-example"
- }
- }
- ]
- }
- ]
- }
-}{
- "apiVersion": "v1",
- "kind": "Service",
- "metadata": {
- "annotations": {
- "konghq.com/connect-timeout": "5000",
- "konghq.com/override": "example-service-upstream",
- "konghq.com/path": "/v1",
- "konghq.com/plugins": "example-service-rate-limiting-advanced",
- "konghq.com/protocol": "http",
- "konghq.com/read-timeout": "60000",
- "konghq.com/retries": "5",
- "konghq.com/write-timeout": "60000"
- },
- "name": "example-service"
- },
- "spec": {
- "ports": [
- {
- "port": 80,
- "protocol": "TCP",
- "targetPort": 80
- }
- ],
- "selector": {
- "app": "example-service"
- }
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "key-auth-example-user"
- },
- "stringData": {
- "key": "my_api_key",
- "kongCredType": "key-auth"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "jwt-auth-example-user"
- },
- "stringData": {
- "algorithm": "HS256",
- "key": "my_jwt_secret",
- "kongCredType": "jwt",
- "rsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX\nZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3\noWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4\n4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ\nDfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw\nO/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6\newIDAQAB\n-----END PUBLIC KEY-----",
- "secret": "my_secret_key"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "basic-auth-example-user"
- },
- "stringData": {
- "kongCredType": "basic-auth",
- "password": "my_basic_password",
- "username": "my_basic_user"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "acl-group-example-user"
- },
- "stringData": {
- "group": "acl_group",
- "kongCredType": "acl"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "mtls-auth-example-user"
- },
- "stringData": {
- "id": "cce8c384-721f-4f58-85dd-50834e3e733a",
- "kongCredType": "mtls-auth",
- "subject_name": "example-user@example.com"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa\nMBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw\nNjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG\nSM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx\n7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB\n/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2\nScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR\nPSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ\n-----END CERTIFICATE-----\n",
- "ca.digest": "f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow\nGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2\nMTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0\nZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of\ne0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE\nQ8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3\nZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl\n-----END CERTIFICATE-----\n",
- "ca.digest": "dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo\nMCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2\nMTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS\nb290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB\nmy/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws\nY9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw\nBgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw\nFoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc\nazM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX\ngxUhveuHBXMWnzUbn6U=\n-----END CERTIFICATE-----\n",
- "ca.digest": "45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy\nb3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu\neLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD\n/WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz\nm5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F\nuCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT\nEP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA\nAaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw\nADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI\nhvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4\npJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS\nGdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM\novZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9\nFk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj\nEwxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ\nP+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi\n53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat\nIoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q\nXxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i\nlIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy\nE56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU\ntyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda\nDZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj\nDv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW\nnYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5\nRNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo\nkQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/\nzmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5\nSrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C\n4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO\nP0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu\nreoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC\nrDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI\nkOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg\nECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm\nzKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2\nfXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu\nLwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY\niVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3\nNNSvLxPAempmiFPSk9AtobYV\n-----END PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10\nbHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN\nBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1\nBYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo\nbyOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu\n3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z\n0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO\n1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa\n71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn\n3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2\nOsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD\nPgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj\nvdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD\n55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE\nAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl\ncnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME\nGDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l\nBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ\nWELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY\nI58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC\nXb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ\nIpmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa\naQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5\nT8tqV6i5miKWwvfZ\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN RSA PRIVATE KEY-----\nMIIJKQIBAAKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1BYCn1+E9Uwgh0uwAenT/\nDKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTobyOUV6tIJAjvzyEOpC45\n8hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu3D6r8/zbhhWAqe4EIt+N\nVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z0xDqCSMmPebzjns03ttB\n29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO1mmABAQTQWMR/00+QI0x\ntvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa71zNzARUVaZ2vy1pRVr0\nDZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn3M/roNLAU+3nz4itpt/z\nf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2OsqQuICaajnW7t1oDd7z\n1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywDPgnhSz9AaoVWhR+GHIPr\njRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAjvdLuNhx4bJbwLBgNGsJM\nkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD55NecBPNw5C9BR0CAwEA\nAQKCAgEAymuOrG/hJKiS2oX8tm8eWFZIELI9BigYozYhCzQexpSGqjwEXOf1H5sB\n0YQjIAlZwhrc57OK7KpGZ6x2BgUT1JZZqs80CBtWxIXuuF5rpje7id8MTLCNuTzb\nr+L2O4Mad0QNI5lKLH5mbt3yhiJ3NnQLHBpODjbpXGDFtTVne1hkJe5MfC1/psyt\nwguO6HllcTTWl93ruonpZPtz39qhYuz4MCAnE5DRUrjO+Mn7y7XoyUS+xnSRl7BD\nbqWRicJQyB+P7px3WyZQri+6TsCQ164iw2D64bLC1oCfLvLSBeh0g3gOdAX5mGTl\nRBpf98LdFJXSmXHodcYMlO5THqHu7mOE8zvPDbOzpwKftE11PS+lhuq/fREJnrAx\npbvTkv2c1nu90gkracv6PhRC8YhBIa2gqhoxY7rH7UpYa1c5QaJzg5ibiteTLRKC\ne9ZmfoPWaY2ksY4gBWZ/p2wokJ8U6ZHEsEfQS9WibMpqRsdINWQ9JnIBLKnTuqB0\nB29E9jHAl8rwMT2/DiIiVjHcdwpP37MxotKvYDFw+yDcZDeKTIh133XZNWyO/TcH\naDrNB0dymqunuNmfPts566AYErym0ndcmmLuGIKKE+l1h1+5CWjdsTdrkkXZK/w1\ni/krfLruQqQcW3Bpng8JAKirvGfYJxIEaCLqtepb7YaHhaI3gz0CggEBAPO0UQ6e\noPzMYmEegp2LjAfHZhwGV0fpiC6nxEWKoEE7Tb5zyB8rlkFIpQlXmljQvf3xDmq/\nTa3JlkaY290oFc0ypp9zUY/sUGyc3pvltxl0gLKOPnIkoP3ma2HzBxQRrGRdcFhH\nAHom80Bm9APm29L0MFuOuhGGxkGvQCxH+KmmohvZMUEqNIuWi8XB7maDXcAmSJ7x\nYdQAgLspRJ+kkZM+59XijyvYvg04xCu1FSop+Lol+xBwWAR5OaKnbZ9L+jKtzbxC\nIS7ERTlhsham2dYIm7SFcD/OcLV6luqreR0svS6HQis1kGxnNxkBAbrB1QZ+wLKp\nQztnOk70H/eWP5sCggEBAOLllCHuRloqEyzDT5sVbflCMTVsXmHGJ4/qI4An+etI\n3DComNLPAIBKYAiNgqWAm/wfLy5rHu2ZGzcPn7cQF/xKp00uDGKncQz3Z9JDofI1\nrpLH+t3LJ9l/EzQv1tpzwOU5rhFNmqrJnwy17BtOmlCKAQnVmyDkLyR9AhWkCTi8\nBLDq6mx1X61K6P11GAxAd70NFNzD8868Ddq2XInwEwXzf/FHQW/JVYZEAa7dn4KF\nwQ/tPSspP0vGzDfgNI64PtNePnZ/e00XXqA7la2OScro+SDSyXGlDKX4XhwwTDD1\n+u3VbUmjInpEJL3bU8c/qe36UhoseF1G0cm22sHqhacCggEAY3A+5r05KQ1oUwJ0\n/z2ybHYjJuo7cN9MLuVLg6iVzSgah8yMapOJYqf2l0JEe1rpOxXB8TKPyoqHo9S5\nWZsCklDJhiQysowVIMw9VNU9ichsvu6lckOZ4R/Ezxmv2LOBaQ5rScnm2vDLroqT\npIftSD1VAfbR21bnzGNqxuazAt44JS7RFyrWd+J8s7t2wCN3/HBij2Akr7Fo1XV4\nR7+JmtA/HpmsG5L7sT9pZAAmW6b2k1XuBH4im+iu6LxyUV5Z/5XFbbx597AkIs7H\nMNDx75BhoB4WeCKPAK29qJFBAPOBWdvc1u6rOGBBLhWoFAEFH/pWPFAuW626L/8S\nkB6hYwKCAQB3/JIec2Pu0Gs9c7eIOofilXdyWfF7YQ+Q0m+dmQZXvzr53F6ctGz+\natZoD3V0UhOq+063DFzZpuq2bmO2qiMU/uGENgLEtOlawwa7MZrVfD/qTSjD22gi\nY0njghzrfuUWEy+S5OgSwvaCAT5vnlyKlMBB1BzqAuFPOXA9w3ZA82TDribz3goP\nmRqm1iI2cG0ho2ZR7KnkvJvS+jbrlvJoZkFVdaoMFHtOum3tbDOrEVJsOrfrOC/J\nwcJDFiSVCKfonOEJRxcMSHx43amkkydAz3zXN8DhgTe0GSijXYMdLSdaWFAn7cYQ\nxDJt2CtwpaEWQRbj0nqAUTAlrLX4cC3nAoIBAQCl1cV86bYw8CKrCuf9TF0Kk5pd\nREdilDpks4Z1RH4MpBDWLtvMeQqlNsN+/RugKQExO0HTdZIyn7cBRRloD2xcNcJA\nG/rUMel/x4fhaEOE7Uw9rmTefvpcgWmtXw64sMA8KFA4oCXIcgbwL5Q+szqNNWAN\nabpgl0DnU06YyBDoK/7D0B8Kt3qS1N6XX+Z5wtPvglbD2HCYy6rdkqi8IbQ/6OeS\nwG7p/7g3JlOEyotMq9Cl2T0wTNDSLlma+mwc9mILITDXznWiLQSznE69mebWBUr3\nSbt91efH30inRx85H0pNJrpZsH0A6ayL0gTJSuUc0eJXYR5Po1gRQMOSIEWh\n-----END RSA PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "consumerGroups": [
- "example-consumer-group"
- ],
- "credentials": [
- "key-auth-example-user",
- "jwt-auth-example-user",
- "basic-auth-example-user",
- "acl-group-example-user",
- "mtls-auth-example-user"
- ],
- "custom_id": "1234567890",
- "kind": "KongConsumer",
- "metadata": {
- "annotations": {
- "konghq.com/plugins": "example-user-rate-limiting-advanced",
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user"
- },
- "username": "example-user"
-}{
- "apiVersion": "configuration.konghq.com/v1beta1",
- "kind": "KongConsumerGroup",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-consumer-group"
- }
-}
\ No newline at end of file
diff --git a/kong2kic/testdata/kicv2_gateway/output-expected.yaml b/kong2kic/testdata/kicv2_gateway/output-expected.yaml
deleted file mode 100644
index 484b07206..000000000
--- a/kong2kic/testdata/kicv2_gateway/output-expected.yaml
+++ /dev/null
@@ -1,1181 +0,0 @@
-apiVersion: configuration.konghq.com/v1
-kind: KongIngress
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service-upstream
-upstream:
- algorithm: round-robin
- hash_fallback: none
- hash_on: none
- hash_on_cookie_path: /
- healthchecks:
- active:
- concurrency: 10
- headers:
- x-another-header:
- - bla
- x-my-header:
- - foo
- - bar
- healthy:
- http_statuses:
- - 200
- - 302
- interval: 0
- successes: 0
- http_path: /
- https_sni: example.com
- https_verify_certificate: true
- timeout: 1
- type: http
- unhealthy:
- http_failures: 0
- http_statuses:
- - 429
- - 404
- - 500
- - 501
- - 502
- - 503
- - 504
- - 505
- interval: 0
- tcp_failures: 0
- timeouts: 0
- passive:
- healthy:
- http_statuses:
- - 200
- - 201
- - 202
- - 203
- - 204
- - 205
- - 206
- - 207
- - 208
- - 226
- - 300
- - 301
- - 302
- - 303
- - 304
- - 305
- - 306
- - 307
- - 308
- successes: 0
- type: http
- unhealthy:
- http_failures: 0
- http_statuses:
- - 429
- - 500
- - 503
- tcp_failures: 0
- timeouts: 0
- threshold: 0
- host_header: example.com
- slots: 10000
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- aws_key: my_key
- aws_region: us-west-2
- aws_secret: my_secret
- function_name: my_function
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long9344b5559f
-plugin: aws-lambda
----
-apiVersion: configuration.konghq.com/v1
-config:
- credentials: true
- exposed_headers:
- - X-My-Header
- headers:
- - Authorization
- max_age: 3600
- methods:
- - GET
- - POST
- origins:
- - example.com
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longfdeaa51f90
-plugin: cors
----
-apiVersion: configuration.konghq.com/v1
-config:
- path: /var/log/kong/kong.log
- reopen: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
-plugin: file-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- content_type: application/json
- http_endpoint: http://example.com/logs
- keepalive: 60000
- method: POST
- queue_size: 1000
- retry_count: 10
- timeout: 10000
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long59030a424c
-plugin: http-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - 192.168.0.1/24
- deny:
- - 192.168.0.2/32
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb44edd01cf
-plugin: ip-restriction
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longef35b834c6
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- message: Forbidden
- status_code: 403
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2c08ebc54
-plugin: request-termination
----
-apiVersion: configuration.konghq.com/v1
-config:
- limits:
- limit_name:
- minute: 10
- policy: local
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longc400f1ab11
-plugin: response-ratelimiting
----
-apiVersion: configuration.konghq.com/v1
-config:
- host: example.com
- port: 1234
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long47f9f5054d
-plugin: tcp-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long26f9714514
-plugin: basic-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- anonymous: null
- claims_to_verify:
- - exp
- - nbf
- header_names:
- - Authorization
- key_claim_name: kid
- maximum_expiration: 3600
- run_on_preflight: true
- secret_is_base64: false
- uri_param_names:
- - token
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long0239c8f63e
-plugin: jwt
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
- key_in_body: false
- key_names:
- - apikey
- run_on_preflight: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long5494737f3e
-plugin: key-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- ca_certificates:
- - cce8c384-721f-4f58-85dd-50834e3e733a
- revocation_check_mode: SKIP
- skip_consumer_lookup: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
-plugin: mtls-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - admin
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2440ac898
-plugin: acl
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-user-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: gateway.networking.k8s.io/v1beta1
-kind: HTTPRoute
-metadata:
- annotations:
- konghq.com/https-redirect-status-code: "302"
- konghq.com/preserve-host: "true"
- konghq.com/regex-priority: "1"
- konghq.com/snis: example.com
- konghq.com/strip-path: "false"
- name: example-service--route-thisisaveryvery-long2093a020ca
-spec:
- hostnames:
- - example.com
- - another-example.com
- - yet-another-example.com
- parentRefs:
- - name: kong
- rules:
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: GET
- path:
- type: RegularExpression
- value: /v1/example/?$
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: POST
- path:
- type: RegularExpression
- value: /v1/example/?$
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: GET
- path:
- type: PathPrefix
- value: /v1/another-example
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: POST
- path:
- type: PathPrefix
- value: /v1/another-example
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: GET
- path:
- type: PathPrefix
- value: /v1/yet-another-example
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: POST
- path:
- type: PathPrefix
- value: /v1/yet-another-example
----
-apiVersion: v1
-kind: Service
-metadata:
- annotations:
- konghq.com/connect-timeout: "5000"
- konghq.com/override: example-service-upstream
- konghq.com/path: /v1
- konghq.com/plugins: example-service-rate-limiting-advanced
- konghq.com/protocol: http
- konghq.com/read-timeout: "60000"
- konghq.com/retries: "5"
- konghq.com/write-timeout: "60000"
- name: example-service
-spec:
- ports:
- - port: 80
- protocol: TCP
- targetPort: 80
- selector:
- app: example-service
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: key-auth-example-user
-stringData:
- key: my_api_key
- kongCredType: key-auth
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: jwt-auth-example-user
-stringData:
- algorithm: HS256
- key: my_jwt_secret
- kongCredType: jwt
- rsa_public_key: |-
- -----BEGIN PUBLIC KEY-----
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX
- ZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3
- oWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4
- 4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ
- DfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw
- O/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6
- ewIDAQAB
- -----END PUBLIC KEY-----
- secret: my_secret_key
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: basic-auth-example-user
-stringData:
- kongCredType: basic-auth
- password: my_basic_password
- username: my_basic_user
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: acl-group-example-user
-stringData:
- group: acl_group
- kongCredType: acl
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: mtls-auth-example-user
-stringData:
- id: cce8c384-721f-4f58-85dd-50834e3e733a
- kongCredType: mtls-auth
- subject_name: example-user@example.com
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa
- MBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw
- NjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG
- SM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx
- 7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB
- /wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2
- ScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR
- PSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ
- -----END CERTIFICATE-----
- ca.digest: f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow
- GAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2
- MTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0
- ZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of
- e0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM
- o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E
- FgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE
- Q8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3
- ZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl
- -----END CERTIFICATE-----
- ca.digest: dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo
- MCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2
- MTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS
- b290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB
- my/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws
- Y9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw
- BgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw
- FoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc
- azM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX
- gxUhveuHBXMWnzUbn6U=
- -----END CERTIFICATE-----
- ca.digest: 45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy
- b3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw
- DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu
- eLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD
- /WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz
- m5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F
- uCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT
- EP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA
- AaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw
- ADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI
- hvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4
- pJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS
- GdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM
- ovZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9
- Fk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj
- Ewxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN PRIVATE KEY-----
- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ
- P+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi
- 53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat
- IoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q
- XxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i
- lIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy
- E56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU
- tyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda
- DZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj
- Dv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW
- nYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5
- RNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo
- kQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/
- zmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5
- SrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C
- 4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO
- P0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu
- reoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC
- rDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI
- kOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg
- ECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm
- zKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2
- fXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu
- LwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY
- iVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3
- NNSvLxPAempmiFPSk9AtobYV
- -----END PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10
- bHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN
- BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1
- BYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo
- byOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu
- 3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z
- 0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO
- 1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa
- 71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn
- 3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2
- OsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD
- PgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj
- vdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD
- 55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE
- AwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl
- cnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME
- GDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l
- BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ
- WELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY
- I58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC
- Xb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ
- Ipmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa
- aQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5
- T8tqV6i5miKWwvfZ
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN RSA PRIVATE KEY-----
- MIIJKQIBAAKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1BYCn1+E9Uwgh0uwAenT/
- DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTobyOUV6tIJAjvzyEOpC45
- 8hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu3D6r8/zbhhWAqe4EIt+N
- VYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z0xDqCSMmPebzjns03ttB
- 29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO1mmABAQTQWMR/00+QI0x
- tvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa71zNzARUVaZ2vy1pRVr0
- DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn3M/roNLAU+3nz4itpt/z
- f+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2OsqQuICaajnW7t1oDd7z
- 1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywDPgnhSz9AaoVWhR+GHIPr
- jRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAjvdLuNhx4bJbwLBgNGsJM
- kupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD55NecBPNw5C9BR0CAwEA
- AQKCAgEAymuOrG/hJKiS2oX8tm8eWFZIELI9BigYozYhCzQexpSGqjwEXOf1H5sB
- 0YQjIAlZwhrc57OK7KpGZ6x2BgUT1JZZqs80CBtWxIXuuF5rpje7id8MTLCNuTzb
- r+L2O4Mad0QNI5lKLH5mbt3yhiJ3NnQLHBpODjbpXGDFtTVne1hkJe5MfC1/psyt
- wguO6HllcTTWl93ruonpZPtz39qhYuz4MCAnE5DRUrjO+Mn7y7XoyUS+xnSRl7BD
- bqWRicJQyB+P7px3WyZQri+6TsCQ164iw2D64bLC1oCfLvLSBeh0g3gOdAX5mGTl
- RBpf98LdFJXSmXHodcYMlO5THqHu7mOE8zvPDbOzpwKftE11PS+lhuq/fREJnrAx
- pbvTkv2c1nu90gkracv6PhRC8YhBIa2gqhoxY7rH7UpYa1c5QaJzg5ibiteTLRKC
- e9ZmfoPWaY2ksY4gBWZ/p2wokJ8U6ZHEsEfQS9WibMpqRsdINWQ9JnIBLKnTuqB0
- B29E9jHAl8rwMT2/DiIiVjHcdwpP37MxotKvYDFw+yDcZDeKTIh133XZNWyO/TcH
- aDrNB0dymqunuNmfPts566AYErym0ndcmmLuGIKKE+l1h1+5CWjdsTdrkkXZK/w1
- i/krfLruQqQcW3Bpng8JAKirvGfYJxIEaCLqtepb7YaHhaI3gz0CggEBAPO0UQ6e
- oPzMYmEegp2LjAfHZhwGV0fpiC6nxEWKoEE7Tb5zyB8rlkFIpQlXmljQvf3xDmq/
- Ta3JlkaY290oFc0ypp9zUY/sUGyc3pvltxl0gLKOPnIkoP3ma2HzBxQRrGRdcFhH
- AHom80Bm9APm29L0MFuOuhGGxkGvQCxH+KmmohvZMUEqNIuWi8XB7maDXcAmSJ7x
- YdQAgLspRJ+kkZM+59XijyvYvg04xCu1FSop+Lol+xBwWAR5OaKnbZ9L+jKtzbxC
- IS7ERTlhsham2dYIm7SFcD/OcLV6luqreR0svS6HQis1kGxnNxkBAbrB1QZ+wLKp
- QztnOk70H/eWP5sCggEBAOLllCHuRloqEyzDT5sVbflCMTVsXmHGJ4/qI4An+etI
- 3DComNLPAIBKYAiNgqWAm/wfLy5rHu2ZGzcPn7cQF/xKp00uDGKncQz3Z9JDofI1
- rpLH+t3LJ9l/EzQv1tpzwOU5rhFNmqrJnwy17BtOmlCKAQnVmyDkLyR9AhWkCTi8
- BLDq6mx1X61K6P11GAxAd70NFNzD8868Ddq2XInwEwXzf/FHQW/JVYZEAa7dn4KF
- wQ/tPSspP0vGzDfgNI64PtNePnZ/e00XXqA7la2OScro+SDSyXGlDKX4XhwwTDD1
- +u3VbUmjInpEJL3bU8c/qe36UhoseF1G0cm22sHqhacCggEAY3A+5r05KQ1oUwJ0
- /z2ybHYjJuo7cN9MLuVLg6iVzSgah8yMapOJYqf2l0JEe1rpOxXB8TKPyoqHo9S5
- WZsCklDJhiQysowVIMw9VNU9ichsvu6lckOZ4R/Ezxmv2LOBaQ5rScnm2vDLroqT
- pIftSD1VAfbR21bnzGNqxuazAt44JS7RFyrWd+J8s7t2wCN3/HBij2Akr7Fo1XV4
- R7+JmtA/HpmsG5L7sT9pZAAmW6b2k1XuBH4im+iu6LxyUV5Z/5XFbbx597AkIs7H
- MNDx75BhoB4WeCKPAK29qJFBAPOBWdvc1u6rOGBBLhWoFAEFH/pWPFAuW626L/8S
- kB6hYwKCAQB3/JIec2Pu0Gs9c7eIOofilXdyWfF7YQ+Q0m+dmQZXvzr53F6ctGz+
- atZoD3V0UhOq+063DFzZpuq2bmO2qiMU/uGENgLEtOlawwa7MZrVfD/qTSjD22gi
- Y0njghzrfuUWEy+S5OgSwvaCAT5vnlyKlMBB1BzqAuFPOXA9w3ZA82TDribz3goP
- mRqm1iI2cG0ho2ZR7KnkvJvS+jbrlvJoZkFVdaoMFHtOum3tbDOrEVJsOrfrOC/J
- wcJDFiSVCKfonOEJRxcMSHx43amkkydAz3zXN8DhgTe0GSijXYMdLSdaWFAn7cYQ
- xDJt2CtwpaEWQRbj0nqAUTAlrLX4cC3nAoIBAQCl1cV86bYw8CKrCuf9TF0Kk5pd
- REdilDpks4Z1RH4MpBDWLtvMeQqlNsN+/RugKQExO0HTdZIyn7cBRRloD2xcNcJA
- G/rUMel/x4fhaEOE7Uw9rmTefvpcgWmtXw64sMA8KFA4oCXIcgbwL5Q+szqNNWAN
- abpgl0DnU06YyBDoK/7D0B8Kt3qS1N6XX+Z5wtPvglbD2HCYy6rdkqi8IbQ/6OeS
- wG7p/7g3JlOEyotMq9Cl2T0wTNDSLlma+mwc9mILITDXznWiLQSznE69mebWBUr3
- Sbt91efH30inRx85H0pNJrpZsH0A6ayL0gTJSuUc0eJXYR5Po1gRQMOSIEWh
- -----END RSA PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: configuration.konghq.com/v1
-consumerGroups:
-- example-consumer-group
-credentials:
-- key-auth-example-user
-- jwt-auth-example-user
-- basic-auth-example-user
-- acl-group-example-user
-- mtls-auth-example-user
-custom_id: "1234567890"
-kind: KongConsumer
-metadata:
- annotations:
- konghq.com/plugins: example-user-rate-limiting-advanced
- kubernetes.io/ingress.class: kong
- name: example-user
-username: example-user
----
-apiVersion: configuration.konghq.com/v1beta1
-kind: KongConsumerGroup
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-consumer-group
----
diff --git a/kong2kic/testdata/kicv2_ingress/output-expected.json b/kong2kic/testdata/kicv2_ingress/output-expected.json
deleted file mode 100644
index 37e4191ed..000000000
--- a/kong2kic/testdata/kicv2_ingress/output-expected.json
+++ /dev/null
@@ -1,750 +0,0 @@
-{
- "apiVersion": "configuration.konghq.com/v1",
- "kind": "KongIngress",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service-upstream"
- },
- "upstream": {
- "algorithm": "round-robin",
- "hash_fallback": "none",
- "hash_on": "none",
- "hash_on_cookie_path": "/",
- "healthchecks": {
- "active": {
- "concurrency": 10,
- "headers": {
- "x-another-header": [
- "bla"
- ],
- "x-my-header": [
- "foo",
- "bar"
- ]
- },
- "healthy": {
- "http_statuses": [
- 200,
- 302
- ],
- "interval": 0,
- "successes": 0
- },
- "http_path": "/",
- "https_sni": "example.com",
- "https_verify_certificate": true,
- "timeout": 1,
- "type": "http",
- "unhealthy": {
- "http_failures": 0,
- "http_statuses": [
- 429,
- 404,
- 500,
- 501,
- 502,
- 503,
- 504,
- 505
- ],
- "interval": 0,
- "tcp_failures": 0,
- "timeouts": 0
- }
- },
- "passive": {
- "healthy": {
- "http_statuses": [
- 200,
- 201,
- 202,
- 203,
- 204,
- 205,
- 206,
- 207,
- 208,
- 226,
- 300,
- 301,
- 302,
- 303,
- 304,
- 305,
- 306,
- 307,
- 308
- ],
- "successes": 0
- },
- "type": "http",
- "unhealthy": {
- "http_failures": 0,
- "http_statuses": [
- 429,
- 500,
- 503
- ],
- "tcp_failures": 0,
- "timeouts": 0
- }
- },
- "threshold": 0
- },
- "host_header": "example.com",
- "slots": 10000
- }
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "aws_key": "my_key",
- "aws_region": "us-west-2",
- "aws_secret": "my_secret",
- "function_name": "my_function"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "plugin": "aws-lambda"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "credentials": true,
- "exposed_headers": [
- "X-My-Header"
- ],
- "headers": [
- "Authorization"
- ],
- "max_age": 3600,
- "methods": [
- "GET",
- "POST"
- ],
- "origins": [
- "example.com"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "plugin": "cors"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "path": "/var/log/kong/kong.log",
- "reopen": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "plugin": "file-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "content_type": "application/json",
- "http_endpoint": "http://example.com/logs",
- "keepalive": 60000,
- "method": "POST",
- "queue_size": 1000,
- "retry_count": 10,
- "timeout": 10000
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "plugin": "http-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "192.168.0.1/24"
- ],
- "deny": [
- "192.168.0.2/32"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "plugin": "ip-restriction"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "message": "Forbidden",
- "status_code": 403
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "plugin": "request-termination"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "limits": {
- "limit_name": {
- "minute": 10
- }
- },
- "policy": "local"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "plugin": "response-ratelimiting"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "host": "example.com",
- "port": 1234
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "plugin": "tcp-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "plugin": "basic-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "anonymous": null,
- "claims_to_verify": [
- "exp",
- "nbf"
- ],
- "header_names": [
- "Authorization"
- ],
- "key_claim_name": "kid",
- "maximum_expiration": 3600,
- "run_on_preflight": true,
- "secret_is_base64": false,
- "uri_param_names": [
- "token"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "plugin": "jwt"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false,
- "key_in_body": false,
- "key_names": [
- "apikey"
- ],
- "run_on_preflight": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "plugin": "key-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "ca_certificates": [
- "cce8c384-721f-4f58-85dd-50834e3e733a"
- ],
- "revocation_check_mode": "SKIP",
- "skip_consumer_lookup": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "plugin": "mtls-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "admin"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "plugin": "acl"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "networking.k8s.io/v1",
- "kind": "Ingress",
- "metadata": {
- "annotations": {
- "konghq.com/headers.x-another-header": "first-header-value,second-header-value",
- "konghq.com/headers.x-my-header": "~*foos?bar$",
- "konghq.com/https-redirect-status-code": "302",
- "konghq.com/methods": "GET,POST",
- "konghq.com/plugins": "example-service--route-thisisaveryvery-long9344b5559f,example-service--route-thisisaveryvery-longfdeaa51f90,example-service--route-thisisaveryvery-long3b4b1fae8e,example-service--route-thisisaveryvery-long59030a424c,example-service--route-thisisaveryvery-longb44edd01cf,example-service--route-thisisaveryvery-longef35b834c6,example-service--route-thisisaveryvery-longb2c08ebc54,example-service--route-thisisaveryvery-longc400f1ab11,example-service--route-thisisaveryvery-long47f9f5054d,example-service--route-thisisaveryvery-long26f9714514,example-service--route-thisisaveryvery-long0239c8f63e,example-service--route-thisisaveryvery-long5494737f3e,example-service--route-thisisaveryvery-long89ae2d2b5d,example-service--route-thisisaveryvery-longb2440ac898",
- "konghq.com/preserve-host": "true",
- "konghq.com/protocols": "http,https",
- "konghq.com/regex-priority": "1",
- "konghq.com/snis": "example.com",
- "konghq.com/strip-path": "false"
- },
- "name": "example-service--route-thisisaveryvery-long2093a020ca"
- },
- "spec": {
- "ingressClassName": "kong",
- "rules": [
- {
- "host": "example.com",
- "http": {
- "paths": [
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/~/v1/example/?$",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/another-example",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/yet-another-example",
- "pathType": "ImplementationSpecific"
- }
- ]
- }
- },
- {
- "host": "another-example.com",
- "http": {
- "paths": [
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/~/v1/example/?$",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/another-example",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/yet-another-example",
- "pathType": "ImplementationSpecific"
- }
- ]
- }
- },
- {
- "host": "yet-another-example.com",
- "http": {
- "paths": [
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/~/v1/example/?$",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/another-example",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/yet-another-example",
- "pathType": "ImplementationSpecific"
- }
- ]
- }
- }
- ]
- }
-}{
- "apiVersion": "v1",
- "kind": "Service",
- "metadata": {
- "annotations": {
- "konghq.com/connect-timeout": "5000",
- "konghq.com/override": "example-service-upstream",
- "konghq.com/path": "/v1",
- "konghq.com/plugins": "example-service-rate-limiting-advanced",
- "konghq.com/protocol": "http",
- "konghq.com/read-timeout": "60000",
- "konghq.com/retries": "5",
- "konghq.com/write-timeout": "60000"
- },
- "name": "example-service"
- },
- "spec": {
- "ports": [
- {
- "port": 80,
- "protocol": "TCP",
- "targetPort": 80
- }
- ],
- "selector": {
- "app": "example-service"
- }
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "key-auth-example-user"
- },
- "stringData": {
- "key": "my_api_key",
- "kongCredType": "key-auth"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "jwt-auth-example-user"
- },
- "stringData": {
- "algorithm": "HS256",
- "key": "my_jwt_secret",
- "kongCredType": "jwt",
- "rsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX\nZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3\noWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4\n4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ\nDfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw\nO/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6\newIDAQAB\n-----END PUBLIC KEY-----",
- "secret": "my_secret_key"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "basic-auth-example-user"
- },
- "stringData": {
- "kongCredType": "basic-auth",
- "password": "my_basic_password",
- "username": "my_basic_user"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "acl-group-example-user"
- },
- "stringData": {
- "group": "acl_group",
- "kongCredType": "acl"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "mtls-auth-example-user"
- },
- "stringData": {
- "id": "cce8c384-721f-4f58-85dd-50834e3e733a",
- "kongCredType": "mtls-auth",
- "subject_name": "example-user@example.com"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa\nMBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw\nNjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG\nSM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx\n7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB\n/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2\nScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR\nPSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ\n-----END CERTIFICATE-----\n",
- "ca.digest": "f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow\nGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2\nMTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0\nZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of\ne0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE\nQ8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3\nZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl\n-----END CERTIFICATE-----\n",
- "ca.digest": "dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo\nMCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2\nMTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS\nb290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB\nmy/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws\nY9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw\nBgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw\nFoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc\nazM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX\ngxUhveuHBXMWnzUbn6U=\n-----END CERTIFICATE-----\n",
- "ca.digest": "45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy\nb3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu\neLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD\n/WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz\nm5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F\nuCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT\nEP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA\nAaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw\nADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI\nhvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4\npJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS\nGdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM\novZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9\nFk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj\nEwxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ\nP+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi\n53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat\nIoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q\nXxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i\nlIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy\nE56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU\ntyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda\nDZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj\nDv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW\nnYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5\nRNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo\nkQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/\nzmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5\nSrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C\n4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO\nP0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu\nreoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC\nrDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI\nkOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg\nECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm\nzKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2\nfXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu\nLwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY\niVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3\nNNSvLxPAempmiFPSk9AtobYV\n-----END PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10\nbHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN\nBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1\nBYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo\nbyOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu\n3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z\n0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO\n1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa\n71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn\n3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2\nOsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD\nPgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj\nvdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD\n55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE\nAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl\ncnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME\nGDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l\nBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ\nWELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY\nI58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC\nXb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ\nIpmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa\naQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5\nT8tqV6i5miKWwvfZ\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "consumerGroups": [
- "example-consumer-group"
- ],
- "credentials": [
- "key-auth-example-user",
- "jwt-auth-example-user",
- "basic-auth-example-user",
- "acl-group-example-user",
- "mtls-auth-example-user"
- ],
- "custom_id": "1234567890",
- "kind": "KongConsumer",
- "metadata": {
- "annotations": {
- "konghq.com/plugins": "example-user-rate-limiting-advanced",
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user"
- },
- "username": "example-user"
-}{
- "apiVersion": "configuration.konghq.com/v1beta1",
- "kind": "KongConsumerGroup",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-consumer-group"
- }
-}
\ No newline at end of file
diff --git a/kong2kic/testdata/kicv2_ingress/output-expected.yaml b/kong2kic/testdata/kicv2_ingress/output-expected.yaml
deleted file mode 100644
index a6b26955d..000000000
--- a/kong2kic/testdata/kicv2_ingress/output-expected.yaml
+++ /dev/null
@@ -1,737 +0,0 @@
-apiVersion: configuration.konghq.com/v1
-kind: KongIngress
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service-upstream
-upstream:
- algorithm: round-robin
- hash_fallback: none
- hash_on: none
- hash_on_cookie_path: /
- healthchecks:
- active:
- concurrency: 10
- headers:
- x-another-header:
- - bla
- x-my-header:
- - foo
- - bar
- healthy:
- http_statuses:
- - 200
- - 302
- interval: 0
- successes: 0
- http_path: /
- https_sni: example.com
- https_verify_certificate: true
- timeout: 1
- type: http
- unhealthy:
- http_failures: 0
- http_statuses:
- - 429
- - 404
- - 500
- - 501
- - 502
- - 503
- - 504
- - 505
- interval: 0
- tcp_failures: 0
- timeouts: 0
- passive:
- healthy:
- http_statuses:
- - 200
- - 201
- - 202
- - 203
- - 204
- - 205
- - 206
- - 207
- - 208
- - 226
- - 300
- - 301
- - 302
- - 303
- - 304
- - 305
- - 306
- - 307
- - 308
- successes: 0
- type: http
- unhealthy:
- http_failures: 0
- http_statuses:
- - 429
- - 500
- - 503
- tcp_failures: 0
- timeouts: 0
- threshold: 0
- host_header: example.com
- slots: 10000
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- aws_key: my_key
- aws_region: us-west-2
- aws_secret: my_secret
- function_name: my_function
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long9344b5559f
-plugin: aws-lambda
----
-apiVersion: configuration.konghq.com/v1
-config:
- credentials: true
- exposed_headers:
- - X-My-Header
- headers:
- - Authorization
- max_age: 3600
- methods:
- - GET
- - POST
- origins:
- - example.com
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longfdeaa51f90
-plugin: cors
----
-apiVersion: configuration.konghq.com/v1
-config:
- path: /var/log/kong/kong.log
- reopen: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
-plugin: file-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- content_type: application/json
- http_endpoint: http://example.com/logs
- keepalive: 60000
- method: POST
- queue_size: 1000
- retry_count: 10
- timeout: 10000
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long59030a424c
-plugin: http-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - 192.168.0.1/24
- deny:
- - 192.168.0.2/32
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb44edd01cf
-plugin: ip-restriction
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longef35b834c6
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- message: Forbidden
- status_code: 403
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2c08ebc54
-plugin: request-termination
----
-apiVersion: configuration.konghq.com/v1
-config:
- limits:
- limit_name:
- minute: 10
- policy: local
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longc400f1ab11
-plugin: response-ratelimiting
----
-apiVersion: configuration.konghq.com/v1
-config:
- host: example.com
- port: 1234
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long47f9f5054d
-plugin: tcp-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long26f9714514
-plugin: basic-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- anonymous: null
- claims_to_verify:
- - exp
- - nbf
- header_names:
- - Authorization
- key_claim_name: kid
- maximum_expiration: 3600
- run_on_preflight: true
- secret_is_base64: false
- uri_param_names:
- - token
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long0239c8f63e
-plugin: jwt
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
- key_in_body: false
- key_names:
- - apikey
- run_on_preflight: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long5494737f3e
-plugin: key-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- ca_certificates:
- - cce8c384-721f-4f58-85dd-50834e3e733a
- revocation_check_mode: SKIP
- skip_consumer_lookup: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
-plugin: mtls-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - admin
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2440ac898
-plugin: acl
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-user-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- annotations:
- konghq.com/headers.x-another-header: first-header-value,second-header-value
- konghq.com/headers.x-my-header: ~*foos?bar$
- konghq.com/https-redirect-status-code: "302"
- konghq.com/methods: GET,POST
- konghq.com/plugins: example-service--route-thisisaveryvery-long9344b5559f,example-service--route-thisisaveryvery-longfdeaa51f90,example-service--route-thisisaveryvery-long3b4b1fae8e,example-service--route-thisisaveryvery-long59030a424c,example-service--route-thisisaveryvery-longb44edd01cf,example-service--route-thisisaveryvery-longef35b834c6,example-service--route-thisisaveryvery-longb2c08ebc54,example-service--route-thisisaveryvery-longc400f1ab11,example-service--route-thisisaveryvery-long47f9f5054d,example-service--route-thisisaveryvery-long26f9714514,example-service--route-thisisaveryvery-long0239c8f63e,example-service--route-thisisaveryvery-long5494737f3e,example-service--route-thisisaveryvery-long89ae2d2b5d,example-service--route-thisisaveryvery-longb2440ac898
- konghq.com/preserve-host: "true"
- konghq.com/protocols: http,https
- konghq.com/regex-priority: "1"
- konghq.com/snis: example.com
- konghq.com/strip-path: "false"
- name: example-service--route-thisisaveryvery-long2093a020ca
-spec:
- ingressClassName: kong
- rules:
- - host: example.com
- http:
- paths:
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /~/v1/example/?$
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/another-example
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/yet-another-example
- pathType: ImplementationSpecific
- - host: another-example.com
- http:
- paths:
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /~/v1/example/?$
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/another-example
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/yet-another-example
- pathType: ImplementationSpecific
- - host: yet-another-example.com
- http:
- paths:
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /~/v1/example/?$
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/another-example
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/yet-another-example
- pathType: ImplementationSpecific
----
-apiVersion: v1
-kind: Service
-metadata:
- annotations:
- konghq.com/connect-timeout: "5000"
- konghq.com/override: example-service-upstream
- konghq.com/path: /v1
- konghq.com/plugins: example-service-rate-limiting-advanced
- konghq.com/protocol: http
- konghq.com/read-timeout: "60000"
- konghq.com/retries: "5"
- konghq.com/write-timeout: "60000"
- name: example-service
-spec:
- ports:
- - port: 80
- protocol: TCP
- targetPort: 80
- selector:
- app: example-service
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: key-auth-example-user
-stringData:
- key: my_api_key
- kongCredType: key-auth
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: jwt-auth-example-user
-stringData:
- algorithm: HS256
- key: my_jwt_secret
- kongCredType: jwt
- rsa_public_key: |-
- -----BEGIN PUBLIC KEY-----
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX
- ZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3
- oWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4
- 4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ
- DfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw
- O/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6
- ewIDAQAB
- -----END PUBLIC KEY-----
- secret: my_secret_key
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: basic-auth-example-user
-stringData:
- kongCredType: basic-auth
- password: my_basic_password
- username: my_basic_user
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: acl-group-example-user
-stringData:
- group: acl_group
- kongCredType: acl
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: mtls-auth-example-user
-stringData:
- id: cce8c384-721f-4f58-85dd-50834e3e733a
- kongCredType: mtls-auth
- subject_name: example-user@example.com
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa
- MBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw
- NjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG
- SM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx
- 7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB
- /wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2
- ScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR
- PSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ
- -----END CERTIFICATE-----
- ca.digest: f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow
- GAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2
- MTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0
- ZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of
- e0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM
- o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E
- FgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE
- Q8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3
- ZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl
- -----END CERTIFICATE-----
- ca.digest: dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo
- MCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2
- MTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS
- b290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB
- my/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws
- Y9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw
- BgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw
- FoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc
- azM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX
- gxUhveuHBXMWnzUbn6U=
- -----END CERTIFICATE-----
- ca.digest: 45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy
- b3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw
- DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu
- eLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD
- /WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz
- m5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F
- uCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT
- EP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA
- AaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw
- ADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI
- hvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4
- pJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS
- GdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM
- ovZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9
- Fk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj
- Ewxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN PRIVATE KEY-----
- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ
- P+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi
- 53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat
- IoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q
- XxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i
- lIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy
- E56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU
- tyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda
- DZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj
- Dv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW
- nYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5
- RNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo
- kQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/
- zmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5
- SrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C
- 4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO
- P0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu
- reoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC
- rDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI
- kOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg
- ECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm
- zKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2
- fXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu
- LwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY
- iVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3
- NNSvLxPAempmiFPSk9AtobYV
- -----END PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10
- bHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN
- BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1
- BYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo
- byOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu
- 3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z
- 0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO
- 1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa
- 71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn
- 3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2
- OsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD
- PgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj
- vdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD
- 55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE
- AwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl
- cnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME
- GDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l
- BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ
- WELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY
- I58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC
- Xb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ
- Ipmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa
- aQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5
- T8tqV6i5miKWwvfZ
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN RSA PRIVATE KEY-----
- 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
- -----END RSA PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: configuration.konghq.com/v1
-consumerGroups:
-- example-consumer-group
-credentials:
-- key-auth-example-user
-- jwt-auth-example-user
-- basic-auth-example-user
-- acl-group-example-user
-- mtls-auth-example-user
-custom_id: "1234567890"
-kind: KongConsumer
-metadata:
- annotations:
- konghq.com/plugins: example-user-rate-limiting-advanced
- kubernetes.io/ingress.class: kong
- name: example-user
-username: example-user
----
-apiVersion: configuration.konghq.com/v1beta1
-kind: KongConsumerGroup
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-consumer-group
----
diff --git a/kong2kic/testdata/kicv3_gateway/output-expected.json b/kong2kic/testdata/kicv3_gateway/output-expected.json
deleted file mode 100644
index 3be1f7ce6..000000000
--- a/kong2kic/testdata/kicv3_gateway/output-expected.json
+++ /dev/null
@@ -1,1486 +0,0 @@
-{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "aws_key": "my_key",
- "aws_region": "us-west-2",
- "aws_secret": "my_secret",
- "function_name": "my_function"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "plugin": "aws-lambda"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "credentials": true,
- "exposed_headers": [
- "X-My-Header"
- ],
- "headers": [
- "Authorization"
- ],
- "max_age": 3600,
- "methods": [
- "GET",
- "POST"
- ],
- "origins": [
- "example.com"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "plugin": "cors"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "path": "/var/log/kong/kong.log",
- "reopen": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "plugin": "file-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "content_type": "application/json",
- "http_endpoint": "http://example.com/logs",
- "keepalive": 60000,
- "method": "POST",
- "queue_size": 1000,
- "retry_count": 10,
- "timeout": 10000
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "plugin": "http-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "192.168.0.1/24"
- ],
- "deny": [
- "192.168.0.2/32"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "plugin": "ip-restriction"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "message": "Forbidden",
- "status_code": 403
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "plugin": "request-termination"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "limits": {
- "limit_name": {
- "minute": 10
- }
- },
- "policy": "local"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "plugin": "response-ratelimiting"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "host": "example.com",
- "port": 1234
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "plugin": "tcp-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "plugin": "basic-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "anonymous": null,
- "claims_to_verify": [
- "exp",
- "nbf"
- ],
- "header_names": [
- "Authorization"
- ],
- "key_claim_name": "kid",
- "maximum_expiration": 3600,
- "run_on_preflight": true,
- "secret_is_base64": false,
- "uri_param_names": [
- "token"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "plugin": "jwt"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false,
- "key_in_body": false,
- "key_names": [
- "apikey"
- ],
- "run_on_preflight": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "plugin": "key-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "ca_certificates": [
- "cce8c384-721f-4f58-85dd-50834e3e733a"
- ],
- "revocation_check_mode": "SKIP",
- "skip_consumer_lookup": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "plugin": "mtls-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "admin"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "plugin": "acl"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "gateway.networking.k8s.io/v1",
- "kind": "HTTPRoute",
- "metadata": {
- "annotations": {
- "konghq.com/https-redirect-status-code": "302",
- "konghq.com/preserve-host": "true",
- "konghq.com/regex-priority": "1",
- "konghq.com/snis": "example.com",
- "konghq.com/strip-path": "false"
- },
- "name": "example-service--route-thisisaveryvery-long2093a020ca"
- },
- "spec": {
- "hostnames": [
- "example.com",
- "another-example.com",
- "yet-another-example.com"
- ],
- "parentRefs": [
- {
- "name": "kong"
- }
- ],
- "rules": [
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "GET",
- "path": {
- "type": "RegularExpression",
- "value": "/v1/example/?$"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "POST",
- "path": {
- "type": "RegularExpression",
- "value": "/v1/example/?$"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "GET",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/another-example"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "POST",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/another-example"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "GET",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/yet-another-example"
- }
- }
- ]
- },
- {
- "backendRefs": [
- {
- "name": "example-service",
- "port": 80
- }
- ],
- "filters": [
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "type": "ExtensionRef"
- },
- {
- "extensionRef": {
- "group": "configuration.konghq.com",
- "kind": "KongPlugin",
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "type": "ExtensionRef"
- }
- ],
- "matches": [
- {
- "headers": [
- {
- "name": "x-another-header",
- "type": "Exact",
- "value": "first-header-value,second-header-value"
- },
- {
- "name": "x-my-header",
- "type": "RegularExpression",
- "value": "foos?bar$"
- }
- ],
- "method": "POST",
- "path": {
- "type": "PathPrefix",
- "value": "/v1/yet-another-example"
- }
- }
- ]
- }
- ]
- }
-}{
- "apiVersion": "configuration.konghq.com/v1beta1",
- "kind": "KongUpstreamPolicy",
- "metadata": {
- "name": "example-service-upstream"
- },
- "spec": {
- "algorithm": "round-robin",
- "healthchecks": {
- "active": {
- "concurrency": 10,
- "headers": {
- "x-another-header": [
- "bla"
- ],
- "x-my-header": [
- "foo",
- "bar"
- ]
- },
- "healthy": {
- "httpStatuses": [
- 200,
- 302
- ],
- "interval": 0,
- "successes": 0
- },
- "httpPath": "/",
- "httpsSni": "example.com",
- "httpsVerifyCertificate": true,
- "timeout": 1,
- "type": "http",
- "unhealthy": {
- "httpFailures": 0,
- "httpStatuses": [
- 429,
- 404,
- 500,
- 501,
- 502,
- 503,
- 504,
- 505
- ],
- "interval": 0,
- "tcpFailures": 0,
- "timeouts": 0
- }
- },
- "passive": {
- "healthy": {
- "httpStatuses": [
- 200,
- 201,
- 202,
- 203,
- 204,
- 205,
- 206,
- 207,
- 208,
- 226,
- 300,
- 301,
- 302,
- 303,
- 304,
- 305,
- 306,
- 307,
- 308
- ],
- "successes": 0
- },
- "type": "http",
- "unhealthy": {
- "httpFailures": 0,
- "httpStatuses": [
- 429,
- 500,
- 503
- ],
- "tcpFailures": 0,
- "timeouts": 0
- }
- },
- "threshold": 0
- },
- "slots": 10000
- }
-}{
- "apiVersion": "v1",
- "kind": "Service",
- "metadata": {
- "annotations": {
- "konghq.com/connect-timeout": "5000",
- "konghq.com/path": "/v1",
- "konghq.com/plugins": "example-service-rate-limiting-advanced",
- "konghq.com/protocol": "http",
- "konghq.com/read-timeout": "60000",
- "konghq.com/retries": "5",
- "konghq.com/upstream-policy": "example-service-upstream",
- "konghq.com/write-timeout": "60000"
- },
- "name": "example-service"
- },
- "spec": {
- "ports": [
- {
- "port": 80,
- "protocol": "TCP",
- "targetPort": 80
- }
- ],
- "selector": {
- "app": "example-service"
- }
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "key-auth"
- },
- "name": "key-auth-example-user"
- },
- "stringData": {
- "key": "my_api_key"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "jwt"
- },
- "name": "jwt-auth-example-user"
- },
- "stringData": {
- "algorithm": "HS256",
- "key": "my_jwt_secret",
- "rsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX\nZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3\noWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4\n4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ\nDfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw\nO/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6\newIDAQAB\n-----END PUBLIC KEY-----",
- "secret": "my_secret_key"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "basic-auth"
- },
- "name": "basic-auth-example-user"
- },
- "stringData": {
- "password": "my_basic_password",
- "username": "my_basic_user"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "acl"
- },
- "name": "acl-group-example-user"
- },
- "stringData": {
- "group": "acl_group"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "mtls-auth"
- },
- "name": "mtls-auth-example-user"
- },
- "stringData": {
- "id": "cce8c384-721f-4f58-85dd-50834e3e733a",
- "subject_name": "example-user@example.com"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa\nMBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw\nNjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG\nSM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx\n7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB\n/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2\nScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR\nPSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ\n-----END CERTIFICATE-----\n",
- "ca.digest": "f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow\nGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2\nMTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0\nZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of\ne0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE\nQ8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3\nZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl\n-----END CERTIFICATE-----\n",
- "ca.digest": "dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo\nMCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2\nMTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS\nb290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB\nmy/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws\nY9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw\nBgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw\nFoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc\nazM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX\ngxUhveuHBXMWnzUbn6U=\n-----END CERTIFICATE-----\n",
- "ca.digest": "45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy\nb3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu\neLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD\n/WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz\nm5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F\nuCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT\nEP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA\nAaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw\nADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI\nhvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4\npJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS\nGdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM\novZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9\nFk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj\nEwxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ\nP+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi\n53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat\nIoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q\nXxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i\nlIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy\nE56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU\ntyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda\nDZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj\nDv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW\nnYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5\nRNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo\nkQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/\nzmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5\nSrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C\n4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO\nP0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu\nreoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC\nrDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI\nkOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg\nECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm\nzKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2\nfXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu\nLwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY\niVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3\nNNSvLxPAempmiFPSk9AtobYV\n-----END PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10\nbHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN\nBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1\nBYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo\nbyOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu\n3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z\n0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO\n1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa\n71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn\n3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2\nOsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD\nPgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj\nvdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD\n55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE\nAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl\ncnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME\nGDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l\nBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ\nWELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY\nI58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC\nXb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ\nIpmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa\naQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5\nT8tqV6i5miKWwvfZ\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "consumerGroups": [
- "example-consumer-group"
- ],
- "credentials": [
- "key-auth-example-user",
- "jwt-auth-example-user",
- "basic-auth-example-user",
- "acl-group-example-user",
- "mtls-auth-example-user"
- ],
- "custom_id": "1234567890",
- "kind": "KongConsumer",
- "metadata": {
- "annotations": {
- "konghq.com/plugins": "example-user-rate-limiting-advanced",
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user"
- },
- "username": "example-user"
-}{
- "apiVersion": "configuration.konghq.com/v1beta1",
- "kind": "KongConsumerGroup",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-consumer-group"
- }
-}
\ No newline at end of file
diff --git a/kong2kic/testdata/kicv3_gateway/output-expected.yaml b/kong2kic/testdata/kicv3_gateway/output-expected.yaml
deleted file mode 100644
index 9077d04df..000000000
--- a/kong2kic/testdata/kicv3_gateway/output-expected.yaml
+++ /dev/null
@@ -1,1180 +0,0 @@
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- aws_key: my_key
- aws_region: us-west-2
- aws_secret: my_secret
- function_name: my_function
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long9344b5559f
-plugin: aws-lambda
----
-apiVersion: configuration.konghq.com/v1
-config:
- credentials: true
- exposed_headers:
- - X-My-Header
- headers:
- - Authorization
- max_age: 3600
- methods:
- - GET
- - POST
- origins:
- - example.com
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longfdeaa51f90
-plugin: cors
----
-apiVersion: configuration.konghq.com/v1
-config:
- path: /var/log/kong/kong.log
- reopen: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
-plugin: file-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- content_type: application/json
- http_endpoint: http://example.com/logs
- keepalive: 60000
- method: POST
- queue_size: 1000
- retry_count: 10
- timeout: 10000
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long59030a424c
-plugin: http-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - 192.168.0.1/24
- deny:
- - 192.168.0.2/32
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb44edd01cf
-plugin: ip-restriction
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longef35b834c6
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- message: Forbidden
- status_code: 403
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2c08ebc54
-plugin: request-termination
----
-apiVersion: configuration.konghq.com/v1
-config:
- limits:
- limit_name:
- minute: 10
- policy: local
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longc400f1ab11
-plugin: response-ratelimiting
----
-apiVersion: configuration.konghq.com/v1
-config:
- host: example.com
- port: 1234
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long47f9f5054d
-plugin: tcp-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long26f9714514
-plugin: basic-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- anonymous: null
- claims_to_verify:
- - exp
- - nbf
- header_names:
- - Authorization
- key_claim_name: kid
- maximum_expiration: 3600
- run_on_preflight: true
- secret_is_base64: false
- uri_param_names:
- - token
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long0239c8f63e
-plugin: jwt
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
- key_in_body: false
- key_names:
- - apikey
- run_on_preflight: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long5494737f3e
-plugin: key-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- ca_certificates:
- - cce8c384-721f-4f58-85dd-50834e3e733a
- revocation_check_mode: SKIP
- skip_consumer_lookup: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
-plugin: mtls-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - admin
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2440ac898
-plugin: acl
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-user-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: gateway.networking.k8s.io/v1
-kind: HTTPRoute
-metadata:
- annotations:
- konghq.com/https-redirect-status-code: "302"
- konghq.com/preserve-host: "true"
- konghq.com/regex-priority: "1"
- konghq.com/snis: example.com
- konghq.com/strip-path: "false"
- name: example-service--route-thisisaveryvery-long2093a020ca
-spec:
- hostnames:
- - example.com
- - another-example.com
- - yet-another-example.com
- parentRefs:
- - name: kong
- rules:
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: GET
- path:
- type: RegularExpression
- value: /v1/example/?$
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: POST
- path:
- type: RegularExpression
- value: /v1/example/?$
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: GET
- path:
- type: PathPrefix
- value: /v1/another-example
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: POST
- path:
- type: PathPrefix
- value: /v1/another-example
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: GET
- path:
- type: PathPrefix
- value: /v1/yet-another-example
- - backendRefs:
- - name: example-service
- port: 80
- filters:
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long9344b5559f
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longfdeaa51f90
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long59030a424c
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb44edd01cf
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longef35b834c6
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2c08ebc54
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longc400f1ab11
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long47f9f5054d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long26f9714514
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long0239c8f63e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long5494737f3e
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
- type: ExtensionRef
- - extensionRef:
- group: configuration.konghq.com
- kind: KongPlugin
- name: example-service--route-thisisaveryvery-longb2440ac898
- type: ExtensionRef
- matches:
- - headers:
- - name: x-another-header
- type: Exact
- value: first-header-value,second-header-value
- - name: x-my-header
- type: RegularExpression
- value: foos?bar$
- method: POST
- path:
- type: PathPrefix
- value: /v1/yet-another-example
----
-apiVersion: configuration.konghq.com/v1beta1
-kind: KongUpstreamPolicy
-metadata:
- name: example-service-upstream
-spec:
- algorithm: round-robin
- healthchecks:
- active:
- concurrency: 10
- headers:
- x-another-header:
- - bla
- x-my-header:
- - foo
- - bar
- healthy:
- httpStatuses:
- - 200
- - 302
- interval: 0
- successes: 0
- httpPath: /
- httpsSni: example.com
- httpsVerifyCertificate: true
- timeout: 1
- type: http
- unhealthy:
- httpFailures: 0
- httpStatuses:
- - 429
- - 404
- - 500
- - 501
- - 502
- - 503
- - 504
- - 505
- interval: 0
- tcpFailures: 0
- timeouts: 0
- passive:
- healthy:
- httpStatuses:
- - 200
- - 201
- - 202
- - 203
- - 204
- - 205
- - 206
- - 207
- - 208
- - 226
- - 300
- - 301
- - 302
- - 303
- - 304
- - 305
- - 306
- - 307
- - 308
- successes: 0
- type: http
- unhealthy:
- httpFailures: 0
- httpStatuses:
- - 429
- - 500
- - 503
- tcpFailures: 0
- timeouts: 0
- threshold: 0
- slots: 10000
----
-apiVersion: v1
-kind: Service
-metadata:
- annotations:
- konghq.com/connect-timeout: "5000"
- konghq.com/path: /v1
- konghq.com/plugins: example-service-rate-limiting-advanced
- konghq.com/protocol: http
- konghq.com/read-timeout: "60000"
- konghq.com/retries: "5"
- konghq.com/upstream-policy: example-service-upstream
- konghq.com/write-timeout: "60000"
- name: example-service
-spec:
- ports:
- - port: 80
- protocol: TCP
- targetPort: 80
- selector:
- app: example-service
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: key-auth
- name: key-auth-example-user
-stringData:
- key: my_api_key
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: jwt
- name: jwt-auth-example-user
-stringData:
- algorithm: HS256
- key: my_jwt_secret
- rsa_public_key: |-
- -----BEGIN PUBLIC KEY-----
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX
- ZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3
- oWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4
- 4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ
- DfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw
- O/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6
- ewIDAQAB
- -----END PUBLIC KEY-----
- secret: my_secret_key
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: basic-auth
- name: basic-auth-example-user
-stringData:
- password: my_basic_password
- username: my_basic_user
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: acl
- name: acl-group-example-user
-stringData:
- group: acl_group
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: mtls-auth
- name: mtls-auth-example-user
-stringData:
- id: cce8c384-721f-4f58-85dd-50834e3e733a
- subject_name: example-user@example.com
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa
- MBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw
- NjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG
- SM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx
- 7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB
- /wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2
- ScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR
- PSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ
- -----END CERTIFICATE-----
- ca.digest: f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow
- GAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2
- MTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0
- ZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of
- e0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM
- o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E
- FgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE
- Q8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3
- ZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl
- -----END CERTIFICATE-----
- ca.digest: dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo
- MCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2
- MTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS
- b290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB
- my/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws
- Y9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw
- BgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw
- FoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc
- azM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX
- gxUhveuHBXMWnzUbn6U=
- -----END CERTIFICATE-----
- ca.digest: 45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy
- b3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw
- DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu
- eLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD
- /WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz
- m5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F
- uCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT
- EP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA
- AaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw
- ADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI
- hvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4
- pJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS
- GdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM
- ovZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9
- Fk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj
- Ewxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN PRIVATE KEY-----
- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ
- P+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi
- 53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat
- IoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q
- XxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i
- lIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy
- E56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU
- tyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda
- DZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj
- Dv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW
- nYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5
- RNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo
- kQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/
- zmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5
- SrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C
- 4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO
- P0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu
- reoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC
- rDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI
- kOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg
- ECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm
- zKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2
- fXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu
- LwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY
- iVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3
- NNSvLxPAempmiFPSk9AtobYV
- -----END PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10
- bHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN
- BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1
- BYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo
- byOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu
- 3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z
- 0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO
- 1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa
- 71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn
- 3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2
- OsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD
- PgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj
- vdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD
- 55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE
- AwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl
- cnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME
- GDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l
- BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ
- WELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY
- I58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC
- Xb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ
- Ipmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa
- aQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5
- T8tqV6i5miKWwvfZ
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN RSA PRIVATE KEY-----
- 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
- -----END RSA PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: configuration.konghq.com/v1
-consumerGroups:
-- example-consumer-group
-credentials:
-- key-auth-example-user
-- jwt-auth-example-user
-- basic-auth-example-user
-- acl-group-example-user
-- mtls-auth-example-user
-custom_id: "1234567890"
-kind: KongConsumer
-metadata:
- annotations:
- konghq.com/plugins: example-user-rate-limiting-advanced
- kubernetes.io/ingress.class: kong
- name: example-user
-username: example-user
----
-apiVersion: configuration.konghq.com/v1beta1
-kind: KongConsumerGroup
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-consumer-group
----
diff --git a/kong2kic/testdata/kicv3_ingress/output-expected.json b/kong2kic/testdata/kicv3_ingress/output-expected.json
deleted file mode 100644
index 2a444ceff..000000000
--- a/kong2kic/testdata/kicv3_ingress/output-expected.json
+++ /dev/null
@@ -1,753 +0,0 @@
-{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "aws_key": "my_key",
- "aws_region": "us-west-2",
- "aws_secret": "my_secret",
- "function_name": "my_function"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long9344b5559f"
- },
- "plugin": "aws-lambda"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "credentials": true,
- "exposed_headers": [
- "X-My-Header"
- ],
- "headers": [
- "Authorization"
- ],
- "max_age": 3600,
- "methods": [
- "GET",
- "POST"
- ],
- "origins": [
- "example.com"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longfdeaa51f90"
- },
- "plugin": "cors"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "path": "/var/log/kong/kong.log",
- "reopen": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long3b4b1fae8e"
- },
- "plugin": "file-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "content_type": "application/json",
- "http_endpoint": "http://example.com/logs",
- "keepalive": 60000,
- "method": "POST",
- "queue_size": 1000,
- "retry_count": 10,
- "timeout": 10000
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long59030a424c"
- },
- "plugin": "http-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "192.168.0.1/24"
- ],
- "deny": [
- "192.168.0.2/32"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb44edd01cf"
- },
- "plugin": "ip-restriction"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longef35b834c6"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "message": "Forbidden",
- "status_code": 403
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2c08ebc54"
- },
- "plugin": "request-termination"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "limits": {
- "limit_name": {
- "minute": 10
- }
- },
- "policy": "local"
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longc400f1ab11"
- },
- "plugin": "response-ratelimiting"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "host": "example.com",
- "port": 1234
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long47f9f5054d"
- },
- "plugin": "tcp-log"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long26f9714514"
- },
- "plugin": "basic-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "anonymous": null,
- "claims_to_verify": [
- "exp",
- "nbf"
- ],
- "header_names": [
- "Authorization"
- ],
- "key_claim_name": "kid",
- "maximum_expiration": 3600,
- "run_on_preflight": true,
- "secret_is_base64": false,
- "uri_param_names": [
- "token"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long0239c8f63e"
- },
- "plugin": "jwt"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_credentials": false,
- "key_in_body": false,
- "key_names": [
- "apikey"
- ],
- "run_on_preflight": true
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long5494737f3e"
- },
- "plugin": "key-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "ca_certificates": [
- "cce8c384-721f-4f58-85dd-50834e3e733a"
- ],
- "revocation_check_mode": "SKIP",
- "skip_consumer_lookup": false
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-long89ae2d2b5d"
- },
- "plugin": "mtls-auth"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "allow": [
- "admin"
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-service--route-thisisaveryvery-longb2440ac898"
- },
- "plugin": "acl"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "config": {
- "hide_client_headers": false,
- "identifier": "consumer",
- "limit": [
- 5
- ],
- "namespace": "example_namespace",
- "strategy": "local",
- "sync_rate": -1,
- "window_size": [
- 30
- ]
- },
- "kind": "KongPlugin",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user-rate-limiting-advanced"
- },
- "plugin": "rate-limiting-advanced"
-}{
- "apiVersion": "networking.k8s.io/v1",
- "kind": "Ingress",
- "metadata": {
- "annotations": {
- "konghq.com/headers.x-another-header": "first-header-value,second-header-value",
- "konghq.com/headers.x-my-header": "~*foos?bar$",
- "konghq.com/https-redirect-status-code": "302",
- "konghq.com/methods": "GET,POST",
- "konghq.com/plugins": "example-service--route-thisisaveryvery-long9344b5559f,example-service--route-thisisaveryvery-longfdeaa51f90,example-service--route-thisisaveryvery-long3b4b1fae8e,example-service--route-thisisaveryvery-long59030a424c,example-service--route-thisisaveryvery-longb44edd01cf,example-service--route-thisisaveryvery-longef35b834c6,example-service--route-thisisaveryvery-longb2c08ebc54,example-service--route-thisisaveryvery-longc400f1ab11,example-service--route-thisisaveryvery-long47f9f5054d,example-service--route-thisisaveryvery-long26f9714514,example-service--route-thisisaveryvery-long0239c8f63e,example-service--route-thisisaveryvery-long5494737f3e,example-service--route-thisisaveryvery-long89ae2d2b5d,example-service--route-thisisaveryvery-longb2440ac898",
- "konghq.com/preserve-host": "true",
- "konghq.com/protocols": "http,https",
- "konghq.com/regex-priority": "1",
- "konghq.com/snis": "example.com",
- "konghq.com/strip-path": "false"
- },
- "name": "example-service--route-thisisaveryvery-long2093a020ca"
- },
- "spec": {
- "ingressClassName": "kong",
- "rules": [
- {
- "host": "example.com",
- "http": {
- "paths": [
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/~/v1/example/?$",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/another-example",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/yet-another-example",
- "pathType": "ImplementationSpecific"
- }
- ]
- }
- },
- {
- "host": "another-example.com",
- "http": {
- "paths": [
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/~/v1/example/?$",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/another-example",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/yet-another-example",
- "pathType": "ImplementationSpecific"
- }
- ]
- }
- },
- {
- "host": "yet-another-example.com",
- "http": {
- "paths": [
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/~/v1/example/?$",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/another-example",
- "pathType": "ImplementationSpecific"
- },
- {
- "backend": {
- "service": {
- "name": "example-service",
- "port": {
- "number": 80
- }
- }
- },
- "path": "/v1/yet-another-example",
- "pathType": "ImplementationSpecific"
- }
- ]
- }
- }
- ]
- }
-}{
- "apiVersion": "configuration.konghq.com/v1beta1",
- "kind": "KongUpstreamPolicy",
- "metadata": {
- "name": "example-service-upstream"
- },
- "spec": {
- "algorithm": "round-robin",
- "healthchecks": {
- "active": {
- "concurrency": 10,
- "headers": {
- "x-another-header": [
- "bla"
- ],
- "x-my-header": [
- "foo",
- "bar"
- ]
- },
- "healthy": {
- "httpStatuses": [
- 200,
- 302
- ],
- "interval": 0,
- "successes": 0
- },
- "httpPath": "/",
- "httpsSni": "example.com",
- "httpsVerifyCertificate": true,
- "timeout": 1,
- "type": "http",
- "unhealthy": {
- "httpFailures": 0,
- "httpStatuses": [
- 429,
- 404,
- 500,
- 501,
- 502,
- 503,
- 504,
- 505
- ],
- "interval": 0,
- "tcpFailures": 0,
- "timeouts": 0
- }
- },
- "passive": {
- "healthy": {
- "httpStatuses": [
- 200,
- 201,
- 202,
- 203,
- 204,
- 205,
- 206,
- 207,
- 208,
- 226,
- 300,
- 301,
- 302,
- 303,
- 304,
- 305,
- 306,
- 307,
- 308
- ],
- "successes": 0
- },
- "type": "http",
- "unhealthy": {
- "httpFailures": 0,
- "httpStatuses": [
- 429,
- 500,
- 503
- ],
- "tcpFailures": 0,
- "timeouts": 0
- }
- },
- "threshold": 0
- },
- "slots": 10000
- }
-}{
- "apiVersion": "v1",
- "kind": "Service",
- "metadata": {
- "annotations": {
- "konghq.com/connect-timeout": "5000",
- "konghq.com/path": "/v1",
- "konghq.com/plugins": "example-service-rate-limiting-advanced",
- "konghq.com/protocol": "http",
- "konghq.com/read-timeout": "60000",
- "konghq.com/retries": "5",
- "konghq.com/upstream-policy": "example-service-upstream",
- "konghq.com/write-timeout": "60000"
- },
- "name": "example-service"
- },
- "spec": {
- "ports": [
- {
- "port": 80,
- "protocol": "TCP",
- "targetPort": 80
- }
- ],
- "selector": {
- "app": "example-service"
- }
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "key-auth"
- },
- "name": "key-auth-example-user"
- },
- "stringData": {
- "key": "my_api_key"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "jwt"
- },
- "name": "jwt-auth-example-user"
- },
- "stringData": {
- "algorithm": "HS256",
- "key": "my_jwt_secret",
- "rsa_public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX\nZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3\noWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4\n4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ\nDfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw\nO/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6\newIDAQAB\n-----END PUBLIC KEY-----",
- "secret": "my_secret_key"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "basic-auth"
- },
- "name": "basic-auth-example-user"
- },
- "stringData": {
- "password": "my_basic_password",
- "username": "my_basic_user"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "acl"
- },
- "name": "acl-group-example-user"
- },
- "stringData": {
- "group": "acl_group"
- }
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "labels": {
- "konghq.com/credential": "mtls-auth"
- },
- "name": "mtls-auth-example-user"
- },
- "stringData": {
- "id": "cce8c384-721f-4f58-85dd-50834e3e733a",
- "subject_name": "example-user@example.com"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa\nMBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw\nNjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG\nSM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx\n7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB\n/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2\nScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR\nPSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ\n-----END CERTIFICATE-----\n",
- "ca.digest": "f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow\nGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2\nMTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0\nZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of\ne0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE\nQ8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3\nZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl\n-----END CERTIFICATE-----\n",
- "ca.digest": "dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf"
- },
- "stringData": {
- "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo\nMCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2\nMTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS\nb290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB\nmy/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws\nY9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw\nBgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw\nFoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc\nazM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX\ngxUhveuHBXMWnzUbn6U=\n-----END CERTIFICATE-----\n",
- "ca.digest": "45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600"
- },
- "type": "Opaque"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy\nb3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu\neLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD\n/WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz\nm5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F\nuCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT\nEP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA\nAaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw\nADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI\nhvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4\npJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS\nGdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM\novZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9\nFk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj\nEwxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ\nP+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi\n53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat\nIoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q\nXxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i\nlIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy\nE56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU\ntyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda\nDZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj\nDv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW\nnYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5\nRNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo\nkQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/\nzmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5\nSrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C\n4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO\nP0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu\nreoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC\nrDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI\nkOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg\nECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm\nzKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2\nfXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu\nLwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY\niVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3\nNNSvLxPAempmiFPSk9AtobYV\n-----END PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "v1",
- "kind": "Secret",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323"
- },
- "stringData": {
- "tls.crt": "-----BEGIN CERTIFICATE-----\nMIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL\nBQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM\nCUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY\nMBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u\nZ2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD\nVQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx\nEDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10\nbHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN\nBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1\nBYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo\nbyOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu\n3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z\n0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO\n1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa\n71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn\n3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2\nOsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD\nPgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj\nvdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD\n55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE\nAwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl\ncnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME\nGDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l\nBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ\nWELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY\nI58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC\nXb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ\nIpmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa\naQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5\nT8tqV6i5miKWwvfZ\n-----END CERTIFICATE-----",
- "tls.key": "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----"
- },
- "type": "kubernetes.io/tls"
-}{
- "apiVersion": "configuration.konghq.com/v1",
- "consumerGroups": [
- "example-consumer-group"
- ],
- "credentials": [
- "key-auth-example-user",
- "jwt-auth-example-user",
- "basic-auth-example-user",
- "acl-group-example-user",
- "mtls-auth-example-user"
- ],
- "custom_id": "1234567890",
- "kind": "KongConsumer",
- "metadata": {
- "annotations": {
- "konghq.com/plugins": "example-user-rate-limiting-advanced",
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-user"
- },
- "username": "example-user"
-}{
- "apiVersion": "configuration.konghq.com/v1beta1",
- "kind": "KongConsumerGroup",
- "metadata": {
- "annotations": {
- "kubernetes.io/ingress.class": "kong"
- },
- "name": "example-consumer-group"
- }
-}
\ No newline at end of file
diff --git a/kong2kic/testdata/kicv3_ingress/output-expected.yaml b/kong2kic/testdata/kicv3_ingress/output-expected.yaml
deleted file mode 100644
index 19dcabdb3..000000000
--- a/kong2kic/testdata/kicv3_ingress/output-expected.yaml
+++ /dev/null
@@ -1,736 +0,0 @@
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- aws_key: my_key
- aws_region: us-west-2
- aws_secret: my_secret
- function_name: my_function
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long9344b5559f
-plugin: aws-lambda
----
-apiVersion: configuration.konghq.com/v1
-config:
- credentials: true
- exposed_headers:
- - X-My-Header
- headers:
- - Authorization
- max_age: 3600
- methods:
- - GET
- - POST
- origins:
- - example.com
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longfdeaa51f90
-plugin: cors
----
-apiVersion: configuration.konghq.com/v1
-config:
- path: /var/log/kong/kong.log
- reopen: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long3b4b1fae8e
-plugin: file-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- content_type: application/json
- http_endpoint: http://example.com/logs
- keepalive: 60000
- method: POST
- queue_size: 1000
- retry_count: 10
- timeout: 10000
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long59030a424c
-plugin: http-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - 192.168.0.1/24
- deny:
- - 192.168.0.2/32
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb44edd01cf
-plugin: ip-restriction
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longef35b834c6
-plugin: rate-limiting-advanced
----
-apiVersion: configuration.konghq.com/v1
-config:
- message: Forbidden
- status_code: 403
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2c08ebc54
-plugin: request-termination
----
-apiVersion: configuration.konghq.com/v1
-config:
- limits:
- limit_name:
- minute: 10
- policy: local
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longc400f1ab11
-plugin: response-ratelimiting
----
-apiVersion: configuration.konghq.com/v1
-config:
- host: example.com
- port: 1234
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long47f9f5054d
-plugin: tcp-log
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long26f9714514
-plugin: basic-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- anonymous: null
- claims_to_verify:
- - exp
- - nbf
- header_names:
- - Authorization
- key_claim_name: kid
- maximum_expiration: 3600
- run_on_preflight: true
- secret_is_base64: false
- uri_param_names:
- - token
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long0239c8f63e
-plugin: jwt
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_credentials: false
- key_in_body: false
- key_names:
- - apikey
- run_on_preflight: true
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long5494737f3e
-plugin: key-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- ca_certificates:
- - cce8c384-721f-4f58-85dd-50834e3e733a
- revocation_check_mode: SKIP
- skip_consumer_lookup: false
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-long89ae2d2b5d
-plugin: mtls-auth
----
-apiVersion: configuration.konghq.com/v1
-config:
- allow:
- - admin
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-service--route-thisisaveryvery-longb2440ac898
-plugin: acl
----
-apiVersion: configuration.konghq.com/v1
-config:
- hide_client_headers: false
- identifier: consumer
- limit:
- - 5
- namespace: example_namespace
- strategy: local
- sync_rate: -1
- window_size:
- - 30
-kind: KongPlugin
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-user-rate-limiting-advanced
-plugin: rate-limiting-advanced
----
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- annotations:
- konghq.com/headers.x-another-header: first-header-value,second-header-value
- konghq.com/headers.x-my-header: ~*foos?bar$
- konghq.com/https-redirect-status-code: "302"
- konghq.com/methods: GET,POST
- konghq.com/plugins: example-service--route-thisisaveryvery-long9344b5559f,example-service--route-thisisaveryvery-longfdeaa51f90,example-service--route-thisisaveryvery-long3b4b1fae8e,example-service--route-thisisaveryvery-long59030a424c,example-service--route-thisisaveryvery-longb44edd01cf,example-service--route-thisisaveryvery-longef35b834c6,example-service--route-thisisaveryvery-longb2c08ebc54,example-service--route-thisisaveryvery-longc400f1ab11,example-service--route-thisisaveryvery-long47f9f5054d,example-service--route-thisisaveryvery-long26f9714514,example-service--route-thisisaveryvery-long0239c8f63e,example-service--route-thisisaveryvery-long5494737f3e,example-service--route-thisisaveryvery-long89ae2d2b5d,example-service--route-thisisaveryvery-longb2440ac898
- konghq.com/preserve-host: "true"
- konghq.com/protocols: http,https
- konghq.com/regex-priority: "1"
- konghq.com/snis: example.com
- konghq.com/strip-path: "false"
- name: example-service--route-thisisaveryvery-long2093a020ca
-spec:
- ingressClassName: kong
- rules:
- - host: example.com
- http:
- paths:
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /~/v1/example/?$
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/another-example
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/yet-another-example
- pathType: ImplementationSpecific
- - host: another-example.com
- http:
- paths:
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /~/v1/example/?$
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/another-example
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/yet-another-example
- pathType: ImplementationSpecific
- - host: yet-another-example.com
- http:
- paths:
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /~/v1/example/?$
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/another-example
- pathType: ImplementationSpecific
- - backend:
- service:
- name: example-service
- port:
- number: 80
- path: /v1/yet-another-example
- pathType: ImplementationSpecific
----
-apiVersion: configuration.konghq.com/v1beta1
-kind: KongUpstreamPolicy
-metadata:
- name: example-service-upstream
-spec:
- algorithm: round-robin
- healthchecks:
- active:
- concurrency: 10
- headers:
- x-another-header:
- - bla
- x-my-header:
- - foo
- - bar
- healthy:
- httpStatuses:
- - 200
- - 302
- interval: 0
- successes: 0
- httpPath: /
- httpsSni: example.com
- httpsVerifyCertificate: true
- timeout: 1
- type: http
- unhealthy:
- httpFailures: 0
- httpStatuses:
- - 429
- - 404
- - 500
- - 501
- - 502
- - 503
- - 504
- - 505
- interval: 0
- tcpFailures: 0
- timeouts: 0
- passive:
- healthy:
- httpStatuses:
- - 200
- - 201
- - 202
- - 203
- - 204
- - 205
- - 206
- - 207
- - 208
- - 226
- - 300
- - 301
- - 302
- - 303
- - 304
- - 305
- - 306
- - 307
- - 308
- successes: 0
- type: http
- unhealthy:
- httpFailures: 0
- httpStatuses:
- - 429
- - 500
- - 503
- tcpFailures: 0
- timeouts: 0
- threshold: 0
- slots: 10000
----
-apiVersion: v1
-kind: Service
-metadata:
- annotations:
- konghq.com/connect-timeout: "5000"
- konghq.com/path: /v1
- konghq.com/plugins: example-service-rate-limiting-advanced
- konghq.com/protocol: http
- konghq.com/read-timeout: "60000"
- konghq.com/retries: "5"
- konghq.com/upstream-policy: example-service-upstream
- konghq.com/write-timeout: "60000"
- name: example-service
-spec:
- ports:
- - port: 80
- protocol: TCP
- targetPort: 80
- selector:
- app: example-service
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: key-auth
- name: key-auth-example-user
-stringData:
- key: my_api_key
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: jwt
- name: jwt-auth-example-user
-stringData:
- algorithm: HS256
- key: my_jwt_secret
- rsa_public_key: |-
- -----BEGIN PUBLIC KEY-----
- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXzYS5yESbekTF3xLiQX
- ZZZfXt0S/nzFp3f2Oux3W7/ydvZ8XSd8+s+wm5oqEcSV9n+5n3ENZbt1A/wgnGI3
- oWrv0yRB9HugzTIGPpI1AQv9Z4p8E44RrB74/uTxYwb9+4yvpuz/fzTt3Gz+Kzc4
- 4fGGq8VpGMFj6AE65ZcOAHHUJe4VuoreBXLYDJcHl2WPIdNKDGscFjElDneLRhWQ
- DfxekDJIQMWCjyBEXacfP6cc9U8Qld6TuVcwi1P2xb8tBDD4MIFL/psfzUhfv1Lw
- O/XZEffJxCqkQn7dsCYy3wpaTjb6XmJ5j0Dbml4f0Bv40Y1mjlAf7C662Mbuguf6
- ewIDAQAB
- -----END PUBLIC KEY-----
- secret: my_secret_key
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: basic-auth
- name: basic-auth-example-user
-stringData:
- password: my_basic_password
- username: my_basic_user
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: acl
- name: acl-group-example-user
-stringData:
- group: acl_group
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- labels:
- konghq.com/credential: mtls-auth
- name: mtls-auth-example-user
-stringData:
- id: cce8c384-721f-4f58-85dd-50834e3e733a
- subject_name: example-user@example.com
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a672ab52d2341203bd70116b456413d7ac3ffc162abbf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBfDCCASKgAwIBAgIRAJqcZC1VSvSQLMN1+7yAeswwCgYIKoZIzj0EAwIwHDEa
- MBgGA1UEAxMRRGVtbyBLb25nIFJvb3QgQ0EwHhcNMjIwNjEzMTMzNzMzWhcNMjcw
- NjEzMTkzNzMzWjAcMRowGAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTBZMBMGByqG
- SM49AgEGCCqGSM49AwEHA0IABOGR89IyhreSHRAi6wp9a5DBIDp4YYSdWzuEdlNx
- 7pX1G4T7x68xUXJZXRUPFyT8Xzn5KwCJm8RVT+nAhrsUx6SjRTBDMA4GA1UdDwEB
- /wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBQ9CUiOPhjp7KD2
- ScRDxX4IzDOrNzAKBggqhkjOPQQDAgNIADBFAiEAw6Dov0c0L++1W9VufAfSMdNR
- PSDfPU0MiUiG59/VIBICIEFn/6c5eQc3hUUBL74/RmNT2b1zxBmp7RiPXJAnAAwJ
- -----END CERTIFICATE-----
- ca.digest: f1baffe9fe9cf8497e38a4271d67fab44423678b7e7c0f677a50f37c113d81b5
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-a4f087c2ee00e6d43cfb4f6884fc1e79f7e6e08e84471
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBqTCCAVCgAwIBAgIQb5LqGa9gS3+Mc2ntWfSoJjAKBggqhkjOPQQDAjAcMRow
- GAYDVQQDExFEZW1vIEtvbmcgUm9vdCBDQTAeFw0yMjA2MTMxMzM5MTVaFw0yMzA2
- MTMxOTM5MTVaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBSb290IEludGVybWVkaWF0
- ZTEgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQImvnSuvXkGy88lvx8a7of
- e0MEMRI2siVvybvWXNpeXXlixgaq7weJ7pewf3HywfO68Va6kn8ehWh7s0D7SLHM
- o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E
- FgQUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwHwYDVR0jBBgwFoAUPQlIjj4Y6eyg9knE
- Q8V+CMwzqzcwCgYIKoZIzj0EAwIDRwAwRAIgNZ+JPA1OqF5DsPapAZ2YsUOgIpn3
- ZbQuYKCAV0SD4EcCIFnfA5rWrc1AgtUw5inJQqJQRNgoPuC14vACqI48BiRl
- -----END CERTIFICATE-----
- ca.digest: dbef7ed285fb292e24f84ffba93c48d92fa322387d85469c460c655abedd5308
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: ca-cert-6b095c7ff377b01252a4dfec59c582fe32934fa7ed0cf
-stringData:
- ca.crt: |
- -----BEGIN CERTIFICATE-----
- MIIBujCCAV+gAwIBAgIRAMkGpj7WZf+2RFE/q7ZhejEwCgYIKoZIzj0EAwIwKjEo
- MCYGA1UEAxMfRGVtbyBLb25nIFJvb3QgSW50ZXJtZWRpYXRlMSBDQTAeFw0yMjA2
- MTMxMzQwNTFaFw0yMjEyMTMwNDQwNTFaMCoxKDAmBgNVBAMTH0RlbW8gS29uZyBS
- b290IEludGVybWVkaWF0ZTIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB
- my/zhZ3F2HvHFqtQzuD3lXX8SeYakxiBQvaGkGSLKD67N3vh7iC2rTSdj/vAs8ws
- Y9X+mXzS6GDKC8PbSX6xo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw
- BgEB/wIBADAdBgNVHQ4EFgQURwCm53YPStZoAMfnVyknH4IgZa4wHwYDVR0jBBgw
- FoAUhuxCKmCSvZWf95+iZ+Wsz9DJJVMwCgYIKoZIzj0EAwIDSQAwRgIhAN1pkUKc
- azM4PiXOnkILB2KBDIF4XpHf+4ThDMODzXP8AiEA45KXA3qMrRPQV1oBfWZ3hLgX
- gxUhveuHBXMWnzUbn6U=
- -----END CERTIFICATE-----
- ca.digest: 45b2b6dd9d4102955b1b1e4b540e677f140521462ed4f22fa5a713863ca84600
-type: Opaque
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-0ee0e1584c8637facac95bd5fce315367dee124c0086d41e
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIECTCCAvGgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyAwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMTUxMTE5NDNaFw0yMjA1MzAxMTE5NDNaMIGRMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFzAVBgNVBAMMDnBy
- b3h5LmtvbmcubGFuMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29uZ2hxLmNvbTCCASIw
- DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJUbKiqoCK1BTNk/7l42n6ukyTEu
- eLyB23e/90PzT/oz8wZzgwTodzbFAS2VtFr1EKqFzor0DrXp9CLnebOdiAR3I6LD
- /WY/x0KW3lx3F35fGiUOSLPTH8zeiDTMx11CcKDxesA+M2/s5q0igkOQ4z4w3voz
- m5a52IcQTSA8K5knNU1qUZBLpc+khxFcaheEK1jsISJJhcdizZBfGdk8S1vpyj5F
- uCZ7oaRvNA6imHjSJwpgo36zd84TgrIgVj9R4QtJysWy/X+bbaKUiKBWwAtd4+DT
- EP90l/ny9szu2fijk4/6k1ntXufGTyvM+J0/qJ13e99TVYOVanITnpTO+6cCAwEA
- AaNWMFQwHwYDVR0jBBgwFoAUdskpf0wJRQxjtzQFZciWmUfl2bcwCQYDVR0TBAIw
- ADALBgNVHQ8EBAMCBPAwGQYDVR0RBBIwEIIOcHJveHkua29uZy5sYW4wDQYJKoZI
- hvcNAQELBQADggEBAJVrTWQRQzNtypa9OXFYADm8Fay1VMop3BY2kh0tfYgQEJ/4
- pJUj6CaszQZ/Aix6LaPnXFcoPCDqqv00mgju86PMamr/zA9USXk8eTmzJkp5RklS
- GdqiXboqESiQVvaNz3kdW7wgNz4FwaGCzkEi/dcc2LdtzLpWizx+TlxMMqjonUUM
- ovZgZo+OlhWRsDVT/qy5SFtA0vlVNtdBr2egXb1H7J8UDC+fax/iKa7+fBUHZOO9
- Fk9U8bxgfQ+jPIVVL8CfAtR68Sos7NpWH0S2emqZRnQvf0MSNdkTQKWn4qR9sckj
- Ewxs5FbrMmgCOgwk1PtgRmdP3RME0HwK/B03saQ=
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN PRIVATE KEY-----
- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCVGyoqqAitQUzZ
- P+5eNp+rpMkxLni8gdt3v/dD80/6M/MGc4ME6Hc2xQEtlbRa9RCqhc6K9A616fQi
- 53mznYgEdyOiw/1mP8dClt5cdxd+XxolDkiz0x/M3og0zMddQnCg8XrAPjNv7Oat
- IoJDkOM+MN76M5uWudiHEE0gPCuZJzVNalGQS6XPpIcRXGoXhCtY7CEiSYXHYs2Q
- XxnZPEtb6co+Rbgme6GkbzQOoph40icKYKN+s3fOE4KyIFY/UeELScrFsv1/m22i
- lIigVsALXePg0xD/dJf58vbM7tn4o5OP+pNZ7V7nxk8rzPidP6idd3vfU1WDlWpy
- E56UzvunAgMBAAECggEAcq7lHNAHdHLgT8yrY41x/AwPryNGO/9JNW7SGVKAdjoU
- tyaLZHAEmXynLk+R28/YFMA8H4Yd9m9OlrYhVjRZFM4p+5vxP/7YHPB7cPUsfcda
- DZxR8PX25JVYf/vtb16V0ERLnKd62qCEwC/lr2A2WHQwXJLrHeAtmZzBJYUCJ5Xj
- Dv1ZhyFjknswaV0vGXe6njTI6CzMQDTGysoagpCCo7RWgzjLREg2BGWd2UQpY4AW
- nYAP4QNt82UMQbgIqsEMj64mzS9Q+o1P84J1naSP5sCI22LeFRp6iezZc+D8EH/5
- RNONGSNWl3g6bsvN1VywYwjWn+waD3XAjXUu+peUgQKBgQDDu1QP28oSMKivHdfo
- kQ1HrTNBRc9eWeAMZFuIbbPLN8rdEibpOm3DwTqithnahqS0NLOsBnXNtuLw1Qr/
- zmOzn0yDO5XG8dlKr9vqWeBLdcRydLJBZwqEzWf4JwwwgfK3rItRaIbnAxnGUTS5
- SrrhNfBAIGS9jx5X2kvLC7hFQQKBgQDDBIrpLTIjRDloWZcu03z9Bhb8jQCyGb5C
- 4MYs+duCnQIdNq/+maPspJzbVmF4b6S1zIPweI3fMvMeqRTbuf+drpElst1buFTO
- P0UMMn4V+4qGIOOkIy5JIKwR8sJD9tNDUPtxuDEotTB9IyWx6pdmCFz5v/bggDCu
- reoqflL+5wKBgQCDvb+L2QS+j4/KJk0flRoaJ2K7SVCVEesyjA3r2uLMImZhvAkC
- rDgbLSDZSbZHFp8fR+WzILoD11gSf2Ki4PjMeqkWH3HlcP0vPwTHTO0h/UdXPmKI
- kOFMl7CmHyoeMCj9JZ60EaXTMYwUpq3VFY6JbTOjBeqoh/8FZMHlDaNewQKBgCHg
- ECEg8KyflTlDFrfTlMp+3E9STuShBCOp18LIRBEUJOHeNgQLvCXHElgnURcSjZHm
- zKRgzIQQ3Zpd1Hm2fWhuglgCEeF0y4ZoBx5vRueaoh1aaTCBy/B39GvJt2UG4vu2
- fXbrf96KWrnh+RJGpbXbjgr0BXZJzisJmrt25gPRAoGBAI3c+INpQXwrE+LBzCPu
- LwIVvkm5NpeIlKQtDNrqG1QvUhqyZ2/Xitc4FyiccW7WHxkGKGZyj7GbmpqEOnyY
- iVku0LSftZgycet2uMdp0HaVAgi5S6aVf5yN0U/8R5ToxcbuEfqwrBIyRgse8lx3
- NNSvLxPAempmiFPSk9AtobYV
- -----END PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: v1
-kind: Secret
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: cert-b12464ec431576239dd9cc2545d528f6cbdbd988cf076323
-stringData:
- tls.crt: |-
- -----BEGIN CERTIFICATE-----
- MIIFeDCCBGCgAwIBAgIUAusYGP9BwoLFFAJdB/jY6eUzUyQwDQYJKoZIhvcNAQEL
- BQAwgZIxCzAJBgNVBAYTAlVLMRIwEAYDVQQIDAlIYW1wc2hpcmUxEjAQBgNVBAcM
- CUFsZGVyc2hvdDEQMA4GA1UECgwHS29uZyBVSzEQMA4GA1UECwwHU3VwcG9ydDEY
- MBYGA1UEAwwPU3VwcG9ydCBSb290IENBMR0wGwYJKoZIhvcNAQkBFg5zdHVAa29u
- Z2hxLmNvbTAeFw0yMTAxMjAxNTA0NDVaFw0yMjAxMjAxNTA0NDVaMIGQMQswCQYD
- VQQGEwJVSzESMBAGA1UECAwJSGFtcHNoaXJlMRIwEAYDVQQHDAlBbGRlcnNob3Qx
- EDAOBgNVBAoMB0tvbmcgVUsxEDAOBgNVBAsMB1N1cHBvcnQxFjAUBgNVBAMMDW10
- bHMtY29uc3VtZXIxHTAbBgkqhkiG9w0BCQEWDnN0dUBrb25naHEuY29tMIICIjAN
- BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1/+83/YNiEVKYvcuVwYGve6afsg1
- BYCn1+E9Uwgh0uwAenT/DKB8NhqoVxc7cZ2HaTI146IGmFICmctlTWvLPLglHmTo
- byOUV6tIJAjvzyEOpC458hLGgbv8mhGXJWPxBVu7Wy6Hapz2bk0cEscfL7PHKaRu
- 3D6r8/zbhhWAqe4EIt+NVYT6baaYBs7bPZQXs/sluKI+DNYuDeaAmoSuCc4ein6z
- 0xDqCSMmPebzjns03ttB29vWL3eYY9dvgoCd+CPhXT/C4CHtvKbH+hOQYDtVF6MO
- 1mmABAQTQWMR/00+QI0xtvuXtEPurla5dA0TN6ddCTOOcILKx62z5oc3Kqr+nHHa
- 71zNzARUVaZ2vy1pRVr0DZgB7KqcFXhy/oy8IpmxUR1ASBDZl6B6RKrdQwvgLgmn
- 3M/roNLAU+3nz4itpt/zf+X0suwdthrflic1R68z1SlYbyoGARWkZ/pOl6kLNVK2
- OsqQuICaajnW7t1oDd7z1+3hm+uoryDwvG6f3T9ZvWjKXYcKg7b+BjbFdahbDywD
- PgnhSz9AaoVWhR+GHIPrjRClMpEkra/yGJFvH3UpXhgg9d0DrLZE51Z75a9SvnAj
- vdLuNhx4bJbwLBgNGsJMkupzBrw4iCfbKFcBbP8o0Xjtarj7T/mkWuQ1GjWqfyrD
- 55NecBPNw5C9BR0CAwEAAaOBxTCBwjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQE
- AwIFoDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENl
- cnRpZmljYXRlMB0GA1UdDgQWBBSV3F+eicU8SVT4LcDJ6eMzP0todzAfBgNVHSME
- GDAWgBR2ySl/TAlFDGO3NAVlyJaZR+XZtzAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0l
- BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBCwUAA4IBAQB5L0OZ
- WELG9Pw6Ol1BsZYgpLR4PGNBB9dKm/9dd+q+ohZVFCfXcjZ3YOU1vh/HHQrALRNY
- I58JxcVCOx/qIW2uA0iSCqIT0sNb9cJLxfZf7X+BzPPPnu0ugUJp7GzLNnHitrLC
- Xb1nmmefwgraNzp+a5IrR8RcQG1mYDuS+2HK/rybo22XcCxhob8OiDEn8+ytkKyQ
- Ipmrf9D+/68/ih6az0w1aakASMmFe8z/p6VgVQkCySCWWFG525BRdGmSImqVZ4xa
- aQFN3L+oN+JJcCFTthLOAYo32JH+xLMz7PokzSL84g3b68h59hXDoMSwB10GthL5
- T8tqV6i5miKWwvfZ
- -----END CERTIFICATE-----
- tls.key: |-
- -----BEGIN RSA PRIVATE KEY-----
- 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
- -----END RSA PRIVATE KEY-----
-type: kubernetes.io/tls
----
-apiVersion: configuration.konghq.com/v1
-consumerGroups:
-- example-consumer-group
-credentials:
-- key-auth-example-user
-- jwt-auth-example-user
-- basic-auth-example-user
-- acl-group-example-user
-- mtls-auth-example-user
-custom_id: "1234567890"
-kind: KongConsumer
-metadata:
- annotations:
- konghq.com/plugins: example-user-rate-limiting-advanced
- kubernetes.io/ingress.class: kong
- name: example-user
-username: example-user
----
-apiVersion: configuration.konghq.com/v1beta1
-kind: KongConsumerGroup
-metadata:
- annotations:
- kubernetes.io/ingress.class: kong
- name: example-consumer-group
----
diff --git a/kong2kic/testdata/route-gw-v2-output-expected.yaml b/kong2kic/testdata/route-gw-v2-output-expected.yaml
new file mode 100644
index 000000000..c6a7cf942
--- /dev/null
+++ b/kong2kic/testdata/route-gw-v2-output-expected.yaml
@@ -0,0 +1,189 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ aws_key: my_key
+ aws_region: us-west-2
+ aws_secret: my_secret
+ function_name: my_function
+kind: KongPlugin
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+plugin: aws-lambda
+---
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: HTTPRoute
+metadata:
+ name: simple-service-simple-route
+spec:
+ parentRefs:
+ - name: kong
+ rules:
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ matches:
+ - path:
+ type: PathPrefix
+ value: /r1
+---
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: HTTPRoute
+metadata:
+ annotations:
+ konghq.com/https-redirect-status-code: "302"
+ konghq.com/preserve-host: "true"
+ konghq.com/regex-priority: "1"
+ konghq.com/snis: example.com
+ konghq.com/strip-path: "false"
+ konghq.com/tags: version:v1
+ name: simple-service--route-thisisaveryvery-long-b00bc5bc73
+spec:
+ hostnames:
+ - example.com
+ - another-example.com
+ - yet-another-example.com
+ parentRefs:
+ - name: kong
+ rules:
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: GET
+ path:
+ type: RegularExpression
+ value: /v1/example/?$
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: POST
+ path:
+ type: RegularExpression
+ value: /v1/example/?$
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: GET
+ path:
+ type: PathPrefix
+ value: /v1/another-example
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: POST
+ path:
+ type: PathPrefix
+ value: /v1/another-example
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: GET
+ path:
+ type: PathPrefix
+ value: /v1/yet-another-example
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: POST
+ path:
+ type: PathPrefix
+ value: /v1/yet-another-example
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ konghq.com/tags: simple-service
+ name: simple-service
+spec:
+ ports:
+ - port: 8080
+ protocol: TCP
+ targetPort: 8080
+ selector:
+ app: simple-service
+---
diff --git a/kong2kic/testdata/route-gw-v3-output-expected.yaml b/kong2kic/testdata/route-gw-v3-output-expected.yaml
new file mode 100644
index 000000000..f757a6c9d
--- /dev/null
+++ b/kong2kic/testdata/route-gw-v3-output-expected.yaml
@@ -0,0 +1,189 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ aws_key: my_key
+ aws_region: us-west-2
+ aws_secret: my_secret
+ function_name: my_function
+kind: KongPlugin
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+plugin: aws-lambda
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: simple-service-simple-route
+spec:
+ parentRefs:
+ - name: kong
+ rules:
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ matches:
+ - path:
+ type: PathPrefix
+ value: /r1
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ annotations:
+ konghq.com/https-redirect-status-code: "302"
+ konghq.com/preserve-host: "true"
+ konghq.com/regex-priority: "1"
+ konghq.com/snis: example.com
+ konghq.com/strip-path: "false"
+ konghq.com/tags: version:v1
+ name: simple-service--route-thisisaveryvery-long-b00bc5bc73
+spec:
+ hostnames:
+ - example.com
+ - another-example.com
+ - yet-another-example.com
+ parentRefs:
+ - name: kong
+ rules:
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: GET
+ path:
+ type: RegularExpression
+ value: /v1/example/?$
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: POST
+ path:
+ type: RegularExpression
+ value: /v1/example/?$
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: GET
+ path:
+ type: PathPrefix
+ value: /v1/another-example
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: POST
+ path:
+ type: PathPrefix
+ value: /v1/another-example
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: GET
+ path:
+ type: PathPrefix
+ value: /v1/yet-another-example
+ - backendRefs:
+ - name: simple-service
+ port: 8080
+ filters:
+ - extensionRef:
+ group: configuration.konghq.com
+ kind: KongPlugin
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+ type: ExtensionRef
+ matches:
+ - headers:
+ - name: x-another-header
+ type: Exact
+ value: first-header-value,second-header-value
+ - name: x-my-header
+ type: RegularExpression
+ value: foos?bar$
+ method: POST
+ path:
+ type: PathPrefix
+ value: /v1/yet-another-example
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ konghq.com/tags: simple-service
+ name: simple-service
+spec:
+ ports:
+ - port: 8080
+ protocol: TCP
+ targetPort: 8080
+ selector:
+ app: simple-service
+---
diff --git a/kong2kic/testdata/route-ingress-output-expected.yaml b/kong2kic/testdata/route-ingress-output-expected.yaml
new file mode 100644
index 000000000..4949b2e51
--- /dev/null
+++ b/kong2kic/testdata/route-ingress-output-expected.yaml
@@ -0,0 +1,136 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ aws_key: my_key
+ aws_region: us-west-2
+ aws_secret: my_secret
+ function_name: my_function
+kind: KongPlugin
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: kong
+ name: simple-service--route-thisisaveryvery-long-6d6e69918e
+plugin: aws-lambda
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: simple-service-simple-route
+spec:
+ ingressClassName: kong
+ rules:
+ - http:
+ paths:
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /r1
+ pathType: ImplementationSpecific
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ annotations:
+ konghq.com/headers.x-another-header: first-header-value,second-header-value
+ konghq.com/headers.x-my-header: ~*foos?bar$
+ konghq.com/https-redirect-status-code: "302"
+ konghq.com/methods: GET,POST
+ konghq.com/plugins: simple-service--route-thisisaveryvery-long-6d6e69918e
+ konghq.com/preserve-host: "true"
+ konghq.com/protocols: http,https
+ konghq.com/regex-priority: "1"
+ konghq.com/snis: example.com
+ konghq.com/strip-path: "false"
+ konghq.com/tags: version:v1
+ name: simple-service--route-thisisaveryvery-long-b00bc5bc73
+spec:
+ ingressClassName: kong
+ rules:
+ - host: example.com
+ http:
+ paths:
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /~/v1/example/?$
+ pathType: ImplementationSpecific
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /v1/another-example
+ pathType: ImplementationSpecific
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /v1/yet-another-example
+ pathType: ImplementationSpecific
+ - host: another-example.com
+ http:
+ paths:
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /~/v1/example/?$
+ pathType: ImplementationSpecific
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /v1/another-example
+ pathType: ImplementationSpecific
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /v1/yet-another-example
+ pathType: ImplementationSpecific
+ - host: yet-another-example.com
+ http:
+ paths:
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /~/v1/example/?$
+ pathType: ImplementationSpecific
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /v1/another-example
+ pathType: ImplementationSpecific
+ - backend:
+ service:
+ name: simple-service
+ port:
+ number: 8080
+ path: /v1/yet-another-example
+ pathType: ImplementationSpecific
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ konghq.com/tags: simple-service
+ name: simple-service
+spec:
+ ports:
+ - port: 8080
+ protocol: TCP
+ targetPort: 8080
+ selector:
+ app: simple-service
+---
diff --git a/kong2kic/testdata/route-input.yaml b/kong2kic/testdata/route-input.yaml
new file mode 100644
index 000000000..d92d271bd
--- /dev/null
+++ b/kong2kic/testdata/route-input.yaml
@@ -0,0 +1,47 @@
+services:
+ - name: simple-service
+ port: 8080
+ tags:
+ - simple-service
+ routes:
+ - name: simple-route
+ paths:
+ - /r1
+ - name: _route_thisISAveryvery_long_+name_toVALIDATEthat(the slugify functionality w0rks4s3xp3ct3d)_
+ methods:
+ - GET
+ - POST
+ hosts:
+ - example.com
+ - another-example.com
+ - yet-another-example.com
+ paths:
+ - ~/v1/example/?$
+ - /v1/another-example
+ - /v1/yet-another-example
+ protocols:
+ - http
+ - https
+ headers:
+ x-my-header:
+ - ~*foos?bar$
+ x-another-header:
+ - first-header-value
+ - second-header-value
+ regex_priority: 1
+ strip_path: false
+ preserve_host: true
+ tags:
+ - version:v1
+ https_redirect_status_code: 302
+ snis:
+ - example.com
+ sources:
+ - ip: 192.168.0.1
+ plugins:
+ - name: aws-lambda
+ config:
+ aws_key: my_key
+ aws_secret: my_secret
+ function_name: my_function
+ aws_region: us-west-2
\ No newline at end of file
diff --git a/kong2kic/testdata/service-input.yaml b/kong2kic/testdata/service-input.yaml
new file mode 100644
index 000000000..1f31d6566
--- /dev/null
+++ b/kong2kic/testdata/service-input.yaml
@@ -0,0 +1,40 @@
+services:
+ - name: complex-service
+ url: http://example-api.com
+ protocol: http
+ host: example-api.com
+ port: 80
+ path: /v1
+ retries: 5
+ connect_timeout: 5000
+ write_timeout: 60000
+ read_timeout: 60000
+ enabled: true
+ client_certificate: 4e3ad2e4-0bc4-4638-8e34-c84a417ba39b
+ tags:
+ - example
+ - api
+ plugins:
+ - name: cors
+ config:
+ origins:
+ - http://mockbin.com
+ methods:
+ - GET
+ - POST
+ headers:
+ - Accept
+ - Accept-Version
+ - Content-Length
+ - Content-MD5
+ - Content-Type
+ - Date
+ - X-Auth-Token
+ exposed_headers:
+ - X-Auth-Token
+ credentials: true
+ max_age: 3600
+ tags:
+ - cors-complex-service
+ - name: simple-service
+ port: 8080
\ No newline at end of file
diff --git a/kong2kic/testdata/service-output-expected.yaml b/kong2kic/testdata/service-output-expected.yaml
new file mode 100644
index 000000000..cfb44d736
--- /dev/null
+++ b/kong2kic/testdata/service-output-expected.yaml
@@ -0,0 +1,61 @@
+apiVersion: configuration.konghq.com/v1
+config:
+ credentials: true
+ exposed_headers:
+ - X-Auth-Token
+ headers:
+ - Accept
+ - Accept-Version
+ - Content-Length
+ - Content-MD5
+ - Content-Type
+ - Date
+ - X-Auth-Token
+ max_age: 3600
+ methods:
+ - GET
+ - POST
+ origins:
+ - http://mockbin.com
+kind: KongPlugin
+metadata:
+ annotations:
+ konghq.com/tags: cors-complex-service
+ kubernetes.io/ingress.class: kong
+ name: complex-service-cors
+plugin: cors
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ konghq.com/client-cert: 4e3ad2e4-0bc4-4638-8e34-c84a417ba39b
+ konghq.com/connect-timeout: "5000"
+ konghq.com/path: /v1
+ konghq.com/plugins: complex-service-cors
+ konghq.com/protocol: http
+ konghq.com/read-timeout: "60000"
+ konghq.com/retries: "5"
+ konghq.com/tags: example,api
+ konghq.com/write-timeout: "60000"
+ name: complex-service
+spec:
+ externalName: example-api.com
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 80
+ type: ExternalName
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: simple-service
+spec:
+ ports:
+ - port: 8080
+ protocol: TCP
+ targetPort: 8080
+ selector:
+ app: simple-service
+---
diff --git a/kong2kic/testdata/upstream-input.yaml b/kong2kic/testdata/upstream-input.yaml
new file mode 100644
index 000000000..b5efdebb0
--- /dev/null
+++ b/kong2kic/testdata/upstream-input.yaml
@@ -0,0 +1,82 @@
+
+services:
+ - name: simple-service
+ host: example-api.com
+ port: 80
+upstreams:
+ - name: example-api.com
+ algorithm: round-robin
+ hash_on: none
+ hash_fallback: none
+ hash_on_cookie_path: "/"
+ slots: 10000
+ healthchecks:
+ passive:
+ type: http
+ healthy:
+ http_statuses:
+ - 200
+ - 201
+ - 202
+ - 203
+ - 204
+ - 205
+ - 206
+ - 207
+ - 208
+ - 226
+ - 300
+ - 301
+ - 302
+ - 303
+ - 304
+ - 305
+ - 306
+ - 307
+ - 308
+ successes: 0
+ unhealthy:
+ http_statuses:
+ - 429
+ - 500
+ - 503
+ timeouts: 0
+ http_failures: 0
+ tcp_failures: 0
+ active:
+ https_verify_certificate: true
+ healthy:
+ http_statuses:
+ - 200
+ - 302
+ successes: 0
+ interval: 0
+ unhealthy:
+ http_failures: 0
+ http_statuses:
+ - 429
+ - 404
+ - 500
+ - 501
+ - 502
+ - 503
+ - 504
+ - 505
+ timeouts: 0
+ tcp_failures: 0
+ interval: 0
+ type: http
+ concurrency: 10
+ headers:
+ x-my-header:
+ - foo
+ - bar
+ x-another-header:
+ - bla
+ timeout: 1
+ http_path: "/"
+ https_sni: example.com
+ threshold: 0
+ tags:
+ - user-level
+ - low-priority
\ No newline at end of file
diff --git a/kong2kic/testdata/upstream-v2-output-expected.yaml b/kong2kic/testdata/upstream-v2-output-expected.yaml
new file mode 100644
index 000000000..da33aef88
--- /dev/null
+++ b/kong2kic/testdata/upstream-v2-output-expected.yaml
@@ -0,0 +1,95 @@
+apiVersion: configuration.konghq.com/v1
+kind: KongIngress
+metadata:
+ annotations:
+ konghq.com/tags: user-level,low-priority
+ kubernetes.io/ingress.class: kong
+ name: simple-service-upstream
+upstream:
+ algorithm: round-robin
+ hash_fallback: none
+ hash_on: none
+ hash_on_cookie_path: /
+ healthchecks:
+ active:
+ concurrency: 10
+ headers:
+ x-another-header:
+ - bla
+ x-my-header:
+ - foo
+ - bar
+ healthy:
+ http_statuses:
+ - 200
+ - 302
+ interval: 0
+ successes: 0
+ http_path: /
+ https_sni: example.com
+ https_verify_certificate: true
+ timeout: 1
+ type: http
+ unhealthy:
+ http_failures: 0
+ http_statuses:
+ - 429
+ - 404
+ - 500
+ - 501
+ - 502
+ - 503
+ - 504
+ - 505
+ interval: 0
+ tcp_failures: 0
+ timeouts: 0
+ passive:
+ healthy:
+ http_statuses:
+ - 200
+ - 201
+ - 202
+ - 203
+ - 204
+ - 205
+ - 206
+ - 207
+ - 208
+ - 226
+ - 300
+ - 301
+ - 302
+ - 303
+ - 304
+ - 305
+ - 306
+ - 307
+ - 308
+ successes: 0
+ type: http
+ unhealthy:
+ http_failures: 0
+ http_statuses:
+ - 429
+ - 500
+ - 503
+ tcp_failures: 0
+ timeouts: 0
+ threshold: 0
+ slots: 10000
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ konghq.com/override: simple-service-upstream
+ name: simple-service
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 80
+ selector:
+ app: simple-service
+---
diff --git a/kong2kic/testdata/upstream-v3-output-expected.yaml b/kong2kic/testdata/upstream-v3-output-expected.yaml
new file mode 100644
index 000000000..253f9a5c3
--- /dev/null
+++ b/kong2kic/testdata/upstream-v3-output-expected.yaml
@@ -0,0 +1,91 @@
+apiVersion: configuration.konghq.com/v1beta1
+kind: KongUpstreamPolicy
+metadata:
+ annotations:
+ konghq.com/tags: user-level,low-priority
+ name: simple-service-upstream
+spec:
+ algorithm: round-robin
+ healthchecks:
+ active:
+ concurrency: 10
+ headers:
+ x-another-header:
+ - bla
+ x-my-header:
+ - foo
+ - bar
+ healthy:
+ httpStatuses:
+ - 200
+ - 302
+ interval: 0
+ successes: 0
+ httpPath: /
+ httpsSni: example.com
+ httpsVerifyCertificate: true
+ timeout: 1
+ type: http
+ unhealthy:
+ httpFailures: 0
+ httpStatuses:
+ - 429
+ - 404
+ - 500
+ - 501
+ - 502
+ - 503
+ - 504
+ - 505
+ interval: 0
+ tcpFailures: 0
+ timeouts: 0
+ passive:
+ healthy:
+ httpStatuses:
+ - 200
+ - 201
+ - 202
+ - 203
+ - 204
+ - 205
+ - 206
+ - 207
+ - 208
+ - 226
+ - 300
+ - 301
+ - 302
+ - 303
+ - 304
+ - 305
+ - 306
+ - 307
+ - 308
+ successes: 0
+ type: http
+ unhealthy:
+ httpFailures: 0
+ httpStatuses:
+ - 429
+ - 500
+ - 503
+ tcpFailures: 0
+ timeouts: 0
+ threshold: 0
+ slots: 10000
+---
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ konghq.com/upstream-policy: simple-service-upstream
+ name: simple-service
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 80
+ selector:
+ app: simple-service
+---
diff --git a/kong2kic/upstream.go b/kong2kic/upstream.go
index 78cee7e67..b27af4bcc 100644
--- a/kong2kic/upstream.go
+++ b/kong2kic/upstream.go
@@ -5,212 +5,239 @@ import (
"strings"
"github.com/kong/go-database-reconciler/pkg/file"
+ "github.com/kong/go-kong/kong"
kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
kicv1beta1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1beta1"
k8scorev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
-// UpstreamPolicy for KIC v3
+// Helper function to find the matching upstream
+func findMatchingUpstream(serviceHost *string, upstreams []file.FUpstream) *file.FUpstream {
+ if serviceHost == nil {
+ return nil
+ }
+ for _, upstream := range upstreams {
+ if upstream.Name != nil && strings.EqualFold(*upstream.Name, *serviceHost) {
+ return &upstream
+ }
+ }
+ return nil
+}
+
+// Helper function to convert HTTP statuses
+func convertHTTPStatuses(statuses []int) []kicv1beta1.HTTPStatus {
+ if statuses == nil {
+ return nil
+ }
+ result := make([]kicv1beta1.HTTPStatus, len(statuses))
+ for i, status := range statuses {
+ result[i] = kicv1beta1.HTTPStatus(status)
+ }
+ return result
+}
+
+// Helper function to populate active healthcheck
+func populateActiveHealthcheck(active *kong.ActiveHealthcheck) *kicv1beta1.KongUpstreamActiveHealthcheck {
+ if active == nil {
+ return nil
+ }
+ return &kicv1beta1.KongUpstreamActiveHealthcheck{
+ Type: active.Type,
+ Concurrency: active.Concurrency,
+ HTTPPath: active.HTTPPath,
+ HTTPSSNI: active.HTTPSSni,
+ HTTPSVerifyCertificate: active.HTTPSVerifyCertificate,
+ Timeout: active.Timeout,
+ Headers: active.Headers,
+ Healthy: populateHealthcheckHealthy(active.Healthy),
+ Unhealthy: populateHealthcheckUnhealthy(active.Unhealthy),
+ }
+}
+
+// Helper function to populate passive healthcheck
+func populatePassiveHealthcheck(passive *kong.PassiveHealthcheck) *kicv1beta1.KongUpstreamPassiveHealthcheck {
+ if passive == nil {
+ return nil
+ }
+ return &kicv1beta1.KongUpstreamPassiveHealthcheck{
+ Type: passive.Type,
+ Healthy: populateHealthcheckHealthy(passive.Healthy),
+ Unhealthy: populateHealthcheckUnhealthy(passive.Unhealthy),
+ }
+}
+
+// Helper function to populate healthcheck healthy settings
+func populateHealthcheckHealthy(healthy *kong.Healthy) *kicv1beta1.KongUpstreamHealthcheckHealthy {
+ if healthy == nil {
+ return nil
+ }
+ return &kicv1beta1.KongUpstreamHealthcheckHealthy{
+ Interval: healthy.Interval,
+ Successes: healthy.Successes,
+ HTTPStatuses: convertHTTPStatuses(healthy.HTTPStatuses),
+ }
+}
+
+// Helper function to populate healthcheck unhealthy settings
+func populateHealthcheckUnhealthy(unhealthy *kong.Unhealthy) *kicv1beta1.KongUpstreamHealthcheckUnhealthy {
+ if unhealthy == nil {
+ return nil
+ }
+ return &kicv1beta1.KongUpstreamHealthcheckUnhealthy{
+ HTTPFailures: unhealthy.HTTPFailures,
+ TCPFailures: unhealthy.TCPFailures,
+ Timeouts: unhealthy.Timeouts,
+ Interval: unhealthy.Interval,
+ HTTPStatuses: convertHTTPStatuses(unhealthy.HTTPStatuses),
+ }
+}
+
+// Function to populate KIC Upstream Policy for KIC v3
func populateKICUpstreamPolicy(
content *file.Content,
service *file.FService,
- k8sservice *k8scorev1.Service,
+ k8sService *k8scorev1.Service,
kicContent *KICContent,
) {
- if content.Upstreams != nil {
- var kongUpstreamPolicy kicv1beta1.KongUpstreamPolicy
- kongUpstreamPolicy.APIVersion = KICAPIVersionV1Beta1
- kongUpstreamPolicy.Kind = UpstreamPolicyKind
- if service.Name != nil {
- kongUpstreamPolicy.ObjectMeta.Name = calculateSlug(*service.Name + "-upstream")
- } else {
- log.Println("Service name is empty. This is not recommended." +
- "Please, provide a name for the service before generating Kong Ingress Controller manifests.")
- return
- }
+ if service.Name == nil {
+ log.Println("Service name is empty. Please provide the necessary information.")
+ return
+ }
+
+ // Find the matching upstream
+ upstream := findMatchingUpstream(service.Host, content.Upstreams)
+ if upstream == nil {
+ return
+ }
- // Find the upstream (if any) whose name matches the service host and copy the upstream
- // into kongUpstreamPolicy. Append the kongUpstreamPolicy to kicContent.KongUpstreamPolicies.
- found := false
- for _, upstream := range content.Upstreams {
- if upstream.Name != nil && strings.EqualFold(*upstream.Name, *service.Host) {
- found = true
- // add an annotation to the k8sservice to link this kongUpstreamPolicy to it
- k8sservice.ObjectMeta.Annotations["konghq.com/upstream-policy"] = kongUpstreamPolicy.ObjectMeta.Name
- var threshold int
- if upstream.Healthchecks != nil && upstream.Healthchecks.Threshold != nil {
- threshold = int(*upstream.Healthchecks.Threshold)
- }
- var activeHealthyHTTPStatuses []kicv1beta1.HTTPStatus
- var activeUnhealthyHTTPStatuses []kicv1beta1.HTTPStatus
- var passiveHealthyHTTPStatuses []kicv1beta1.HTTPStatus
- var passiveUnhealthyHTTPStatuses []kicv1beta1.HTTPStatus
-
- if upstream.Healthchecks != nil &&
- upstream.Healthchecks.Active != nil &&
- upstream.Healthchecks.Active.Healthy != nil {
- activeHealthyHTTPStatuses = make([]kicv1beta1.HTTPStatus, len(upstream.Healthchecks.Active.Healthy.HTTPStatuses))
- for i, status := range upstream.Healthchecks.Active.Healthy.HTTPStatuses {
- activeHealthyHTTPStatuses[i] = kicv1beta1.HTTPStatus(status)
- }
- }
-
- if upstream.Healthchecks != nil &&
- upstream.Healthchecks.Active != nil &&
- upstream.Healthchecks.Active.Unhealthy != nil {
- activeUnhealthyHTTPStatuses = make([]kicv1beta1.HTTPStatus,
- len(upstream.Healthchecks.Active.Unhealthy.HTTPStatuses))
- for i, status := range upstream.Healthchecks.Active.Unhealthy.HTTPStatuses {
- activeUnhealthyHTTPStatuses[i] = kicv1beta1.HTTPStatus(status)
- }
- }
-
- if upstream.Healthchecks != nil &&
- upstream.Healthchecks.Passive != nil &&
- upstream.Healthchecks.Passive.Healthy != nil {
- passiveHealthyHTTPStatuses = make([]kicv1beta1.HTTPStatus, len(upstream.Healthchecks.Passive.Healthy.HTTPStatuses))
- for i, status := range upstream.Healthchecks.Passive.Healthy.HTTPStatuses {
- passiveHealthyHTTPStatuses[i] = kicv1beta1.HTTPStatus(status)
- }
- }
-
- if upstream.Healthchecks != nil &&
- upstream.Healthchecks.Passive != nil &&
- upstream.Healthchecks.Passive.Unhealthy != nil {
- passiveUnhealthyHTTPStatuses = make([]kicv1beta1.HTTPStatus,
- len(upstream.Healthchecks.Passive.Unhealthy.HTTPStatuses))
- for i, status := range upstream.Healthchecks.Passive.Unhealthy.HTTPStatuses {
- passiveUnhealthyHTTPStatuses[i] = kicv1beta1.HTTPStatus(status)
- }
- }
-
- // populeate kongUpstreamPolicy.Spec with the
- // non-nil attributes in upstream.
- if upstream.Algorithm != nil {
- kongUpstreamPolicy.Spec.Algorithm = upstream.Algorithm
- }
- if upstream.Slots != nil {
- kongUpstreamPolicy.Spec.Slots = upstream.Slots
- }
-
- if upstream.HashOn != nil && upstream.Algorithm != nil && *upstream.Algorithm == "consistent-hashing" {
- kongUpstreamPolicy.Spec.HashOn = &kicv1beta1.KongUpstreamHash{
- Input: (*kicv1beta1.HashInput)(upstream.HashOn),
- Header: upstream.HashOnHeader,
- Cookie: upstream.HashOnCookie,
- CookiePath: upstream.HashOnCookiePath,
- QueryArg: upstream.HashOnQueryArg,
- URICapture: upstream.HashOnURICapture,
- }
- }
- if upstream.HashFallback != nil && upstream.Algorithm != nil && *upstream.Algorithm == "consistent-hashing" {
- kongUpstreamPolicy.Spec.HashOnFallback = &kicv1beta1.KongUpstreamHash{
- Input: (*kicv1beta1.HashInput)(upstream.HashFallback),
- Header: upstream.HashFallbackHeader,
- QueryArg: upstream.HashFallbackQueryArg,
- URICapture: upstream.HashFallbackURICapture,
- }
- }
- if upstream.Healthchecks != nil {
- kongUpstreamPolicy.Spec.Healthchecks = &kicv1beta1.KongUpstreamHealthcheck{
- Threshold: &threshold,
- Active: &kicv1beta1.KongUpstreamActiveHealthcheck{
- Type: upstream.Healthchecks.Active.Type,
- Concurrency: upstream.Healthchecks.Active.Concurrency,
- HTTPPath: upstream.Healthchecks.Active.HTTPPath,
- HTTPSSNI: upstream.Healthchecks.Active.HTTPSSni,
- HTTPSVerifyCertificate: upstream.Healthchecks.Active.HTTPSVerifyCertificate,
- Timeout: upstream.Healthchecks.Active.Timeout,
- Headers: upstream.Healthchecks.Active.Headers,
- Healthy: &kicv1beta1.KongUpstreamHealthcheckHealthy{
- Interval: upstream.Healthchecks.Active.Healthy.Interval,
- Successes: upstream.Healthchecks.Active.Healthy.Successes,
- HTTPStatuses: activeHealthyHTTPStatuses,
- },
- Unhealthy: &kicv1beta1.KongUpstreamHealthcheckUnhealthy{
- HTTPFailures: upstream.Healthchecks.Active.Unhealthy.HTTPFailures,
- TCPFailures: upstream.Healthchecks.Active.Unhealthy.TCPFailures,
- Timeouts: upstream.Healthchecks.Active.Unhealthy.Timeouts,
- Interval: upstream.Healthchecks.Active.Unhealthy.Interval,
- HTTPStatuses: activeUnhealthyHTTPStatuses,
- },
- },
- Passive: &kicv1beta1.KongUpstreamPassiveHealthcheck{
- Type: upstream.Healthchecks.Passive.Type,
- Healthy: &kicv1beta1.KongUpstreamHealthcheckHealthy{
- HTTPStatuses: passiveHealthyHTTPStatuses,
- Interval: upstream.Healthchecks.Passive.Healthy.Interval,
- Successes: upstream.Healthchecks.Passive.Healthy.Successes,
- },
- Unhealthy: &kicv1beta1.KongUpstreamHealthcheckUnhealthy{
- HTTPFailures: upstream.Healthchecks.Passive.Unhealthy.HTTPFailures,
- HTTPStatuses: passiveUnhealthyHTTPStatuses,
- TCPFailures: upstream.Healthchecks.Passive.Unhealthy.TCPFailures,
- Timeouts: upstream.Healthchecks.Passive.Unhealthy.Timeouts,
- Interval: upstream.Healthchecks.Passive.Unhealthy.Interval,
- },
- },
- }
- }
+ // Create KongUpstreamPolicy
+ kongUpstreamPolicy := kicv1beta1.KongUpstreamPolicy{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: KICAPIVersionV1Beta1,
+ Kind: UpstreamPolicyKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(*service.Name + "-upstream"),
+ Annotations: make(map[string]string),
+ },
+ }
+
+ // Add an annotation to link the upstream policy to the k8s service
+ if k8sService.ObjectMeta.Annotations == nil {
+ k8sService.ObjectMeta.Annotations = make(map[string]string)
+ }
+ k8sService.ObjectMeta.Annotations["konghq.com/upstream-policy"] = kongUpstreamPolicy.ObjectMeta.Name
+
+ // Populate the Upstream Policy Spec
+ populateKongUpstreamPolicySpec(upstream, &kongUpstreamPolicy)
+
+ // Add tags to annotations
+ addTagsToAnnotations(upstream.Tags, kongUpstreamPolicy.ObjectMeta.Annotations)
+
+ // Append the KongUpstreamPolicy to KIC content
+ kicContent.KongUpstreamPolicies = append(kicContent.KongUpstreamPolicies, kongUpstreamPolicy)
+}
+
+// Helper function to populate KongUpstreamPolicy Spec
+func populateKongUpstreamPolicySpec(upstream *file.FUpstream, policy *kicv1beta1.KongUpstreamPolicy) {
+ if upstream.Algorithm != nil {
+ policy.Spec.Algorithm = upstream.Algorithm
+ }
+ if upstream.Slots != nil {
+ policy.Spec.Slots = upstream.Slots
+ }
+
+ if upstream.Algorithm != nil && *upstream.Algorithm == "consistent-hashing" {
+ if upstream.HashOn != nil {
+ policy.Spec.HashOn = &kicv1beta1.KongUpstreamHash{
+ Input: (*kicv1beta1.HashInput)(upstream.HashOn),
+ Header: upstream.HashOnHeader,
+ Cookie: upstream.HashOnCookie,
+ CookiePath: upstream.HashOnCookiePath,
+ QueryArg: upstream.HashOnQueryArg,
+ URICapture: upstream.HashOnURICapture,
}
- if found {
- kicContent.KongUpstreamPolicies = append(kicContent.KongUpstreamPolicies, kongUpstreamPolicy)
+ }
+ if upstream.HashFallback != nil {
+ policy.Spec.HashOnFallback = &kicv1beta1.KongUpstreamHash{
+ Input: (*kicv1beta1.HashInput)(upstream.HashFallback),
+ Header: upstream.HashFallbackHeader,
+ QueryArg: upstream.HashFallbackQueryArg,
+ URICapture: upstream.HashFallbackURICapture,
}
}
}
+
+ // Handle healthchecks
+ if upstream.Healthchecks != nil {
+ var threshold int
+ if upstream.Healthchecks.Threshold != nil {
+ threshold = int(*upstream.Healthchecks.Threshold)
+ }
+ policy.Spec.Healthchecks = &kicv1beta1.KongUpstreamHealthcheck{
+ Threshold: &threshold,
+ Active: populateActiveHealthcheck(upstream.Healthchecks.Active),
+ Passive: populatePassiveHealthcheck(upstream.Healthchecks.Passive),
+ }
+ }
}
-// KongIngress with upstream section for KIC v2
+// Function to populate KIC Upstream for KIC v2
func populateKICUpstream(
content *file.Content,
service *file.FService,
- k8sservice *k8scorev1.Service,
+ k8sService *k8scorev1.Service,
kicContent *KICContent,
) {
- // add Kong specific configuration to the k8s service via a KongIngress resource
-
- if content.Upstreams != nil {
- var kongIngress kicv1.KongIngress
- kongIngress.APIVersion = KICAPIVersion
- kongIngress.Kind = IngressKind
- if service.Name != nil {
- kongIngress.ObjectMeta.Name = calculateSlug(*service.Name + "-upstream")
- } else {
- log.Println("Service name is empty. This is not recommended." +
- "Please, provide a name for the service before generating Kong Ingress Controller manifests.")
- return
- }
- kongIngress.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
-
- // add an annotation to the k8sservice to link this kongIngress to it
- k8sservice.ObjectMeta.Annotations["konghq.com/override"] = kongIngress.ObjectMeta.Name
-
- // Find the upstream (if any) whose name matches the service host and copy the upstream
- // into a kicv1.KongIngress resource. Append the kicv1.KongIngress to kicContent.KongIngresses.
- found := false
- for _, upstream := range content.Upstreams {
- if upstream.Name != nil && strings.EqualFold(*upstream.Name, *service.Host) {
- found = true
- kongIngress.Upstream = &kicv1.KongIngressUpstream{
- HostHeader: upstream.HostHeader,
- Algorithm: upstream.Algorithm,
- Slots: upstream.Slots,
- Healthchecks: upstream.Healthchecks,
- HashOn: upstream.HashOn,
- HashFallback: upstream.HashFallback,
- HashOnHeader: upstream.HashOnHeader,
- HashFallbackHeader: upstream.HashFallbackHeader,
- HashOnCookie: upstream.HashOnCookie,
- HashOnCookiePath: upstream.HashOnCookiePath,
- HashOnQueryArg: upstream.HashOnQueryArg,
- HashFallbackQueryArg: upstream.HashFallbackQueryArg,
- HashOnURICapture: upstream.HashOnURICapture,
- HashFallbackURICapture: upstream.HashFallbackURICapture,
- }
- }
- }
- if found {
- kicContent.KongIngresses = append(kicContent.KongIngresses, kongIngress)
- }
+ if service.Name == nil {
+ log.Println("Service name is empty. Please provide the necessary information.")
+ return
+ }
+
+ // Find the matching upstream
+ upstream := findMatchingUpstream(service.Host, content.Upstreams)
+ if upstream == nil {
+ return
+ }
+
+ // Create KongIngress
+ kongIngress := kicv1.KongIngress{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: KICAPIVersion,
+ Kind: IngressKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(*service.Name + "-upstream"),
+ Annotations: map[string]string{IngressClass: ClassName},
+ },
+ Upstream: &kicv1.KongIngressUpstream{
+ HostHeader: upstream.HostHeader,
+ Algorithm: upstream.Algorithm,
+ Slots: upstream.Slots,
+ Healthchecks: upstream.Healthchecks,
+ HashOn: upstream.HashOn,
+ HashFallback: upstream.HashFallback,
+ HashOnHeader: upstream.HashOnHeader,
+ HashFallbackHeader: upstream.HashFallbackHeader,
+ HashOnCookie: upstream.HashOnCookie,
+ HashOnCookiePath: upstream.HashOnCookiePath,
+ HashOnQueryArg: upstream.HashOnQueryArg,
+ HashFallbackQueryArg: upstream.HashFallbackQueryArg,
+ HashOnURICapture: upstream.HashOnURICapture,
+ HashFallbackURICapture: upstream.HashFallbackURICapture,
+ },
}
+
+ // Add an annotation to link the KongIngress to the k8s service
+ if k8sService.ObjectMeta.Annotations == nil {
+ k8sService.ObjectMeta.Annotations = make(map[string]string)
+ }
+ k8sService.ObjectMeta.Annotations["konghq.com/override"] = kongIngress.ObjectMeta.Name
+
+ // Add tags to annotations
+ addTagsToAnnotations(upstream.Tags, kongIngress.ObjectMeta.Annotations)
+
+ // Append the KongIngress to KIC content
+ kicContent.KongIngresses = append(kicContent.KongIngresses, kongIngress)
}
diff --git a/kong2kic/utils.go b/kong2kic/utils.go
new file mode 100644
index 000000000..6b0ba3308
--- /dev/null
+++ b/kong2kic/utils.go
@@ -0,0 +1,94 @@
+package kong2kic
+
+import (
+ "encoding/json"
+ "log"
+ "strings"
+
+ "github.com/kong/go-database-reconciler/pkg/file"
+ "github.com/kong/go-kong/kong"
+ kicv1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/configuration/v1"
+ apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// Helper function to add tags to annotations
+func addTagsToAnnotations(tags []*string, annotations map[string]string) {
+ if tags != nil {
+ var tagList []string
+ for _, tag := range tags {
+ if tag != nil {
+ tagList = append(tagList, *tag)
+ }
+ }
+ if len(tagList) > 0 {
+ annotations["konghq.com/tags"] = strings.Join(tagList, ",")
+ }
+ }
+}
+
+// Helper function to update the "konghq.com/plugins" annotation
+func addPluginToAnnotations(pluginName string, annotations map[string]string) {
+ if existing, ok := annotations["konghq.com/plugins"]; ok && existing != "" {
+ annotations["konghq.com/plugins"] = existing + "," + pluginName
+ } else {
+ annotations["konghq.com/plugins"] = pluginName
+ }
+}
+
+// Helper function to create a KongPlugin from a plugin
+func createKongPlugin(plugin *file.FPlugin, ownerName string) (*kicv1.KongPlugin, error) {
+ if plugin.Name == nil {
+ log.Println("Plugin name is empty. Please provide a name for the plugin.")
+ return nil, nil
+ }
+ pluginName := *plugin.Name
+ kongPlugin := &kicv1.KongPlugin{
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: KICAPIVersion,
+ Kind: KongPluginKind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: calculateSlug(ownerName + "-" + pluginName),
+ Annotations: map[string]string{IngressClass: ClassName},
+ },
+ PluginName: pluginName,
+ }
+
+ // Add tags to annotations
+ addTagsToAnnotations(plugin.Tags, kongPlugin.ObjectMeta.Annotations)
+
+ // Populate enabled, runon, ordering, and protocols
+ if plugin.Enabled != nil {
+ kongPlugin.Disabled = !*plugin.Enabled
+ }
+ if plugin.RunOn != nil {
+ kongPlugin.RunOn = *plugin.RunOn
+ }
+ if plugin.Ordering != nil {
+ kongPlugin.Ordering = &kong.PluginOrdering{
+ Before: plugin.Ordering.Before,
+ After: plugin.Ordering.After,
+ }
+ }
+ if plugin.Protocols != nil {
+ var protocols []string
+ for _, protocol := range plugin.Protocols {
+ if protocol != nil {
+ protocols = append(protocols, *protocol)
+ }
+ }
+ kongPlugin.Protocols = kicv1.StringsToKongProtocols(protocols)
+ }
+
+ // Transform the plugin config
+ configJSON, err := json.Marshal(plugin.Config)
+ if err != nil {
+ return nil, err
+ }
+ kongPlugin.Config = apiextensionsv1.JSON{
+ Raw: configJSON,
+ }
+
+ return kongPlugin, nil
+}
diff --git a/kong2tf/builder_default_terraform.go b/kong2tf/builder_default_terraform.go
index fb11d791f..5c34dc73a 100644
--- a/kong2tf/builder_default_terraform.go
+++ b/kong2tf/builder_default_terraform.go
@@ -40,7 +40,7 @@ func (b *DefaultTerraformBuider) buildControlPlaneVar(controlPlaneID *string) {
cpID = *controlPlaneID
}
b.content += fmt.Sprintf(`variable "control_plane_id" {
- type = "string"
+ type = string
default = "%s"
}`, cpID) + "\n\n"
}
diff --git a/kong2tf/testdata/ca-certificate-output-expected.tf b/kong2tf/testdata/ca-certificate-output-expected.tf
index 90d22b371..72a42e885 100644
--- a/kong2tf/testdata/ca-certificate-output-expected.tf
+++ b/kong2tf/testdata/ca-certificate-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/certificate-sni-output-expected.tf b/kong2tf/testdata/certificate-sni-output-expected.tf
index 28bc8f451..9725ec79c 100644
--- a/kong2tf/testdata/certificate-sni-output-expected.tf
+++ b/kong2tf/testdata/certificate-sni-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-acl-output-expected.tf b/kong2tf/testdata/consumer-acl-output-expected.tf
index daee55d7b..60fe181f7 100644
--- a/kong2tf/testdata/consumer-acl-output-expected.tf
+++ b/kong2tf/testdata/consumer-acl-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-basic-auth-output-expected.tf b/kong2tf/testdata/consumer-basic-auth-output-expected.tf
index c46d19c61..d22995022 100644
--- a/kong2tf/testdata/consumer-basic-auth-output-expected.tf
+++ b/kong2tf/testdata/consumer-basic-auth-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-group-output-expected.tf b/kong2tf/testdata/consumer-group-output-expected.tf
index 7d4ceca0e..22454a2ca 100644
--- a/kong2tf/testdata/consumer-group-output-expected.tf
+++ b/kong2tf/testdata/consumer-group-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-group-plugin-output-expected.tf b/kong2tf/testdata/consumer-group-plugin-output-expected.tf
index 7a8b82d2d..7503a13b5 100644
--- a/kong2tf/testdata/consumer-group-plugin-output-expected.tf
+++ b/kong2tf/testdata/consumer-group-plugin-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-hmac-auth-output-expected.tf b/kong2tf/testdata/consumer-hmac-auth-output-expected.tf
index 24675be71..89132e708 100644
--- a/kong2tf/testdata/consumer-hmac-auth-output-expected.tf
+++ b/kong2tf/testdata/consumer-hmac-auth-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-jwt-output-expected.tf b/kong2tf/testdata/consumer-jwt-output-expected.tf
index b126ce540..1584560d8 100644
--- a/kong2tf/testdata/consumer-jwt-output-expected.tf
+++ b/kong2tf/testdata/consumer-jwt-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-jwt-output-with-imports-expected.tf b/kong2tf/testdata/consumer-jwt-output-with-imports-expected.tf
index 698018209..90fe5429f 100644
--- a/kong2tf/testdata/consumer-jwt-output-with-imports-expected.tf
+++ b/kong2tf/testdata/consumer-jwt-output-with-imports-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "abc-123"
}
diff --git a/kong2tf/testdata/consumer-key-auth-output-expected.tf b/kong2tf/testdata/consumer-key-auth-output-expected.tf
index 753478f3c..b5d23f7e6 100644
--- a/kong2tf/testdata/consumer-key-auth-output-expected.tf
+++ b/kong2tf/testdata/consumer-key-auth-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-no-auth-output-expected.tf b/kong2tf/testdata/consumer-no-auth-output-expected.tf
index d218747a3..ffebc4521 100644
--- a/kong2tf/testdata/consumer-no-auth-output-expected.tf
+++ b/kong2tf/testdata/consumer-no-auth-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/consumer-plugin-output-expected.tf b/kong2tf/testdata/consumer-plugin-output-expected.tf
index 0650f0cad..3e6498557 100644
--- a/kong2tf/testdata/consumer-plugin-output-expected.tf
+++ b/kong2tf/testdata/consumer-plugin-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/global-plugin-oidc-output-expected.tf b/kong2tf/testdata/global-plugin-oidc-output-expected.tf
index 0b402b1f4..d320bc21f 100644
--- a/kong2tf/testdata/global-plugin-oidc-output-expected.tf
+++ b/kong2tf/testdata/global-plugin-oidc-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/global-plugin-rate-limiting-output-expected.tf b/kong2tf/testdata/global-plugin-rate-limiting-output-expected.tf
index 5a19a1acb..4b66fc313 100644
--- a/kong2tf/testdata/global-plugin-rate-limiting-output-expected.tf
+++ b/kong2tf/testdata/global-plugin-rate-limiting-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/route-output-expected.tf b/kong2tf/testdata/route-output-expected.tf
index bc879c61d..e01cf1955 100644
--- a/kong2tf/testdata/route-output-expected.tf
+++ b/kong2tf/testdata/route-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/route-plugin-output-expected.tf b/kong2tf/testdata/route-plugin-output-expected.tf
index 662d8b4ea..f12ff2add 100644
--- a/kong2tf/testdata/route-plugin-output-expected.tf
+++ b/kong2tf/testdata/route-plugin-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/service-output-expected.tf b/kong2tf/testdata/service-output-expected.tf
index 59128051e..39791e6a4 100644
--- a/kong2tf/testdata/service-output-expected.tf
+++ b/kong2tf/testdata/service-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/service-plugin-output-expected.tf b/kong2tf/testdata/service-plugin-output-expected.tf
index ea871a4f1..d52c70693 100644
--- a/kong2tf/testdata/service-plugin-output-expected.tf
+++ b/kong2tf/testdata/service-plugin-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/upstream-target-output-expected.tf b/kong2tf/testdata/upstream-target-output-expected.tf
index fdb9eb0a1..25b2f2d70 100644
--- a/kong2tf/testdata/upstream-target-output-expected.tf
+++ b/kong2tf/testdata/upstream-target-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/kong2tf/testdata/vault-output-expected.tf b/kong2tf/testdata/vault-output-expected.tf
index 1c1af8d8b..1f5e197da 100644
--- a/kong2tf/testdata/vault-output-expected.tf
+++ b/kong2tf/testdata/vault-output-expected.tf
@@ -1,5 +1,5 @@
variable "control_plane_id" {
- type = "string"
+ type = string
default = "YOUR_CONTROL_PLANE_ID"
}
diff --git a/tests/integration/test_utils.go b/tests/integration/test_utils.go
index d1d37f676..41a23b40e 100644
--- a/tests/integration/test_utils.go
+++ b/tests/integration/test_utils.go
@@ -374,3 +374,21 @@ func render(opts ...string) (string, error) {
return stripansi.Strip(string(out)), cmdErr
}
+
+func validate(online bool, opts ...string) error {
+ deckCmd := cmd.NewRootCmd()
+
+ var args []string
+ if online {
+ args = []string{"gateway", "validate"}
+ } else {
+ args = []string{"file", "validate"}
+ }
+
+ if len(opts) > 0 {
+ args = append(args, opts...)
+ }
+ deckCmd.SetArgs(args)
+
+ return deckCmd.ExecuteContext(context.Background())
+}
diff --git a/tests/integration/testdata/validate/kong-ee.yaml b/tests/integration/testdata/validate/kong-ee.yaml
new file mode 100644
index 000000000..460a25741
--- /dev/null
+++ b/tests/integration/testdata/validate/kong-ee.yaml
@@ -0,0 +1,32 @@
+_format_version: "3.0"
+services:
+ - name: example-service
+ url: http://mockbin.org
+ routes:
+ - name: example-route
+ paths:
+ - /mock
+ methods:
+ - GET
+ - POST
+ strip_path: false
+ preserve_host: true
+ plugins:
+ - name: rate-limiting
+ config:
+ minute: 5
+ policy: local
+consumers:
+ - keyauth_credentials:
+ - key: alice-secret-key
+ username: alice
+ - keyauth_credentials:
+ - key: bob-secret-key
+ username: bob
+plugins:
+ - name: key-auth
+ config:
+ key_names:
+ - apikey
+ hide_credentials: true
+ run_on_preflight: true
diff --git a/tests/integration/testdata/validate/kong.yaml b/tests/integration/testdata/validate/kong.yaml
new file mode 100644
index 000000000..da79fdfed
--- /dev/null
+++ b/tests/integration/testdata/validate/kong.yaml
@@ -0,0 +1,16 @@
+_format_version: "1.1"
+services:
+- connect_timeout: 60000
+ id: 58076db2-28b6-423b-ba39-a797193017f7
+ host: mockbin.org
+ name: svc1
+ port: 80
+ protocol: http
+ read_timeout: 60000
+ retries: 5
+ routes:
+ - name: r1
+ id: 87b6a97e-f3f7-4c47-857a-7464cb9e202b
+ https_redirect_status_code: 301
+ paths:
+ - /r1
\ No newline at end of file
diff --git a/tests/integration/testdata/validate/kong3x.yaml b/tests/integration/testdata/validate/kong3x.yaml
new file mode 100644
index 000000000..a6ff52d42
--- /dev/null
+++ b/tests/integration/testdata/validate/kong3x.yaml
@@ -0,0 +1,16 @@
+_format_version: "3.0"
+services:
+- connect_timeout: 60000
+ id: 58076db2-28b6-423b-ba39-a797193017f7
+ host: mockbin.org
+ name: svc1
+ port: 80
+ protocol: http
+ read_timeout: 60000
+ retries: 5
+ routes:
+ - name: r1
+ id: 87b6a97e-f3f7-4c47-857a-7464cb9e202b
+ https_redirect_status_code: 301
+ paths:
+ - /r1
diff --git a/tests/integration/testdata/validate/konnect.yaml b/tests/integration/testdata/validate/konnect.yaml
new file mode 100644
index 000000000..a9fa78b4d
--- /dev/null
+++ b/tests/integration/testdata/validate/konnect.yaml
@@ -0,0 +1,18 @@
+_format_version: "3.0"
+_konnect:
+ control_plane_name: default
+services:
+- connect_timeout: 60000
+ id: 58076db2-28b6-423b-ba39-a797193017f7
+ host: mockbin.org
+ name: svc1
+ port: 80
+ protocol: http
+ read_timeout: 60000
+ retries: 5
+ routes:
+ - name: r1
+ id: 87b6a97e-f3f7-4c47-857a-7464cb9e202b
+ https_redirect_status_code: 301
+ paths:
+ - /r1
\ No newline at end of file
diff --git a/tests/integration/testdata/validate/konnect_1_1.yaml b/tests/integration/testdata/validate/konnect_1_1.yaml
new file mode 100644
index 000000000..839c993db
--- /dev/null
+++ b/tests/integration/testdata/validate/konnect_1_1.yaml
@@ -0,0 +1,18 @@
+_format_version: "1.1"
+_konnect:
+ control_plane_name: default
+services:
+- connect_timeout: 60000
+ id: 58076db2-28b6-423b-ba39-a797193017f7
+ host: mockbin.org
+ name: svc1
+ port: 80
+ protocol: http
+ read_timeout: 60000
+ retries: 5
+ routes:
+ - name: r1
+ id: 87b6a97e-f3f7-4c47-857a-7464cb9e202b
+ https_redirect_status_code: 301
+ paths:
+ - /r1
\ No newline at end of file
diff --git a/tests/integration/testdata/validate/konnect_invalid.yaml b/tests/integration/testdata/validate/konnect_invalid.yaml
new file mode 100644
index 000000000..ec07c8c57
--- /dev/null
+++ b/tests/integration/testdata/validate/konnect_invalid.yaml
@@ -0,0 +1,16 @@
+_format_version: "3.0"
+services:
+- connect_timeout: 60000
+ id: 58076db2-28b6-423b-ba39-a797193017f7
+ host: mockbin.org
+ name: svc1
+ port: 80
+ protocol: http
+ read_timeout: 60000
+ retries: 5
+ routes:
+ - name: r1
+ id: 87b6a97e-f3f7-4c47-857a-7464cb9e202b
+ https_redirect_status_code: 301
+ paths:
+ - /r1
\ No newline at end of file
diff --git a/tests/integration/testdata/validate/konnect_no_version.yaml b/tests/integration/testdata/validate/konnect_no_version.yaml
new file mode 100644
index 000000000..89a2b6bc9
--- /dev/null
+++ b/tests/integration/testdata/validate/konnect_no_version.yaml
@@ -0,0 +1,17 @@
+_konnect:
+ control_plane_name: default
+services:
+- connect_timeout: 60000
+ id: 58076db2-28b6-423b-ba39-a797193017f7
+ host: mockbin.org
+ name: svc1
+ port: 80
+ protocol: http
+ read_timeout: 60000
+ retries: 5
+ routes:
+ - name: r1
+ id: 87b6a97e-f3f7-4c47-857a-7464cb9e202b
+ https_redirect_status_code: 301
+ paths:
+ - /r1
\ No newline at end of file
diff --git a/tests/integration/testdata/validate/rbac-resources.yaml b/tests/integration/testdata/validate/rbac-resources.yaml
new file mode 100644
index 000000000..06ab6e792
--- /dev/null
+++ b/tests/integration/testdata/validate/rbac-resources.yaml
@@ -0,0 +1,93 @@
+_format_version: "3.0"
+_konnect:
+ control_plane_name: default
+rbac_roles:
+- comment: Full access to Dev Portal related endpoints in the workspace
+ endpoint_permissions:
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /developers
+ negative: false
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /developers/*
+ negative: false
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /files
+ negative: false
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /files/*
+ negative: false
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /kong
+ negative: false
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /rbac/*
+ negative: true
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /rbac/*/*
+ negative: true
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /rbac/*/*/*
+ negative: true
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /rbac/*/*/*/*
+ negative: true
+ workspace: default
+ - actions:
+ - read
+ - delete
+ - create
+ - update
+ endpoint: /rbac/*/*/*/*/*
+ negative: true
+ workspace: default
+ - actions:
+ - read
+ - update
+ endpoint: /workspaces/default
+ negative: false
+ workspace: default
+ name: workspace-portal-admin
diff --git a/tests/integration/validate_test.go b/tests/integration/validate_test.go
new file mode 100644
index 000000000..410bce2ef
--- /dev/null
+++ b/tests/integration/validate_test.go
@@ -0,0 +1,235 @@
+//go:build integration
+
+package integration
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+const (
+ ONLINE = true
+ OFFLINE = false
+)
+
+func Test_Validate_Konnect(t *testing.T) {
+ setup(t)
+ runWhen(t, "konnect", "")
+
+ tests := []struct {
+ name string
+ stateFile string
+ additionalArgs []string
+ errorExpected bool
+ errorString string
+ }{
+ {
+ name: "validate with konnect",
+ stateFile: "testdata/validate/konnect.yaml",
+ additionalArgs: []string{},
+ errorExpected: false,
+ },
+ {
+ name: "validate with --konnect-compatibility",
+ stateFile: "testdata/validate/konnect.yaml",
+ additionalArgs: []string{"--konnect-compatibility"},
+ errorExpected: false,
+ },
+ {
+ name: "validate with 1.1 version file",
+ stateFile: "testdata/validate/konnect_1_1.yaml",
+ additionalArgs: []string{},
+ errorExpected: true,
+ errorString: "[version] decK file version must be '3.0' or greater",
+ },
+ {
+ name: "validate with no version in deck file",
+ stateFile: "testdata/validate/konnect_no_version.yaml",
+ additionalArgs: []string{},
+ errorExpected: true,
+ errorString: "[version] unable to determine decK file version",
+ },
+ {
+ name: "validate with --rbac-resources-only",
+ stateFile: "testdata/validate/rbac-resources.yaml",
+ additionalArgs: []string{"--rbac-resources-only"},
+ errorExpected: true,
+ errorString: "[rbac] not yet supported by konnect",
+ },
+ {
+ name: "validate with workspace set",
+ stateFile: "testdata/validate/konnect.yaml",
+ additionalArgs: []string{"--workspace=default"},
+ errorExpected: true,
+ errorString: "[workspaces] not supported by Konnect - use control planes instead",
+ },
+ {
+ name: "validate with no konnect config in file, passed via cli flag konnect control plane",
+ stateFile: "testdata/validate/konnect_invalid.yaml",
+ additionalArgs: []string{"--konnect-control-plane-name=default"},
+ errorExpected: false,
+ },
+ {
+ name: "validate with no konnect config in file, passed via cli flag konnect runtime group",
+ stateFile: "testdata/validate/konnect_invalid.yaml",
+ additionalArgs: []string{"--konnect-runtime-group-name=default"},
+ errorExpected: false,
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ validateOpts := append([]string{
+ tc.stateFile,
+ }, tc.additionalArgs...)
+
+ err := validate(ONLINE, validateOpts...)
+
+ if tc.errorExpected {
+ assert.Error(t, err)
+ if tc.errorString != "" {
+ assert.Contains(t, err.Error(), tc.errorString)
+ }
+ return
+ }
+
+ assert.NoError(t, err)
+ })
+ }
+}
+
+func Test_Validate_File(t *testing.T) {
+ setup(t)
+
+ tests := []struct {
+ name string
+ stateFile string
+ additionalArgs []string
+ errorExpected bool
+ }{
+ {
+ name: "file validate format version 1.1",
+ stateFile: "testdata/validate/kong.yaml",
+ additionalArgs: []string{},
+ },
+ {
+ name: "file validate format version 3.0",
+ stateFile: "testdata/validate/kong3x.yaml",
+ additionalArgs: []string{},
+ },
+ {
+ name: "file validate with --konnect-compatibility",
+ stateFile: "testdata/validate/konnect.yaml",
+ additionalArgs: []string{"--konnect-compatibility"},
+ },
+ {
+ name: "file validate with --workspace",
+ stateFile: "testdata/validate/kong3x.yaml",
+ additionalArgs: []string{"--workspace=default"},
+ },
+ {
+ name: "file validate with --rbac-resources-only",
+ stateFile: "testdata/validate/rbac-resources.yaml",
+ additionalArgs: []string{"--rbac-resources-only"},
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ validateOpts := []string{
+ tc.stateFile,
+ }
+ validateOpts = append(validateOpts, tc.additionalArgs...)
+
+ err := validate(OFFLINE, validateOpts...)
+ assert.NoError(t, err)
+ })
+ }
+}
+
+func Test_Validate_Gateway(t *testing.T) {
+ setup(t)
+ runWhen(t, "kong", ">=2.8.0")
+
+ tests := []struct {
+ name string
+ stateFile string
+ additionalArgs []string
+ errorExpected bool
+ }{
+ {
+ name: "validate format version 1.1",
+ stateFile: "testdata/validate/kong.yaml",
+ additionalArgs: []string{},
+ },
+ {
+ name: "validate format version 3.0",
+ stateFile: "testdata/validate/kong3x.yaml",
+ additionalArgs: []string{},
+ },
+ {
+ name: "validate with --konnect-compatibility",
+ stateFile: "testdata/validate/konnect.yaml",
+ additionalArgs: []string{"--konnect-compatibility"},
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ validateOpts := []string{
+ tc.stateFile,
+ }
+ validateOpts = append(validateOpts, tc.additionalArgs...)
+
+ err := validate(ONLINE, validateOpts...)
+ assert.NoError(t, err)
+ })
+ }
+}
+
+func Test_Validate_Gateway_EE(t *testing.T) {
+ setup(t)
+ runWhen(t, "enterprise", ">=2.8.0")
+
+ tests := []struct {
+ name string
+ stateFile string
+ additionalArgs []string
+ errorExpected bool
+ }{
+ {
+ name: "validate format version 1.1",
+ stateFile: "testdata/validate/kong.yaml",
+ additionalArgs: []string{},
+ },
+ {
+ name: "validate format version 3.0",
+ stateFile: "testdata/validate/kong-ee.yaml",
+ additionalArgs: []string{},
+ },
+ {
+ name: "validate with --konnect-compatibility",
+ stateFile: "testdata/validate/konnect.yaml",
+ additionalArgs: []string{"--konnect-compatibility"},
+ },
+ {
+ name: "validate with --workspace",
+ stateFile: "testdata/validate/kong-ee.yaml",
+ additionalArgs: []string{"--workspace=default"},
+ },
+ // TODO: Add a rbac flag test, once the behaviour is fixed
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ validateOpts := []string{
+ tc.stateFile,
+ }
+ validateOpts = append(validateOpts, tc.additionalArgs...)
+
+ err := validate(ONLINE, validateOpts...)
+ assert.NoError(t, err)
+ })
+ }
+}
diff --git a/validate/konnect_compatibility.go b/validate/konnect_compatibility.go
index 74eb617b7..663ed71d0 100644
--- a/validate/konnect_compatibility.go
+++ b/validate/konnect_compatibility.go
@@ -5,6 +5,7 @@ import (
"fmt"
"strconv"
+ "github.com/kong/go-database-reconciler/pkg/dump"
"github.com/kong/go-database-reconciler/pkg/file"
"github.com/kong/go-kong/kong"
)
@@ -39,14 +40,14 @@ func checkPlugin(name *string, config kong.Configuration) error {
return nil
}
-func KonnectCompatibility(targetContent *file.Content) []error {
+func KonnectCompatibility(targetContent *file.Content, dumpConfig dump.Config) []error {
var errs []error
if targetContent.Workspace != "" {
errs = append(errs, errors.New(errWorkspace))
}
- if targetContent.Konnect == nil {
+ if targetContent.Konnect == nil && dumpConfig.KonnectControlPlane == "" {
errs = append(errs, errors.New(errKonnect))
}
diff --git a/validate/konnect_compatibility_test.go b/validate/konnect_compatibility_test.go
index d4a120580..41a9d9da7 100644
--- a/validate/konnect_compatibility_test.go
+++ b/validate/konnect_compatibility_test.go
@@ -5,6 +5,7 @@ import (
"fmt"
"testing"
+ "github.com/kong/go-database-reconciler/pkg/dump"
"github.com/kong/go-database-reconciler/pkg/file"
"github.com/kong/go-kong/kong"
"github.com/stretchr/testify/assert"
@@ -12,9 +13,10 @@ import (
func Test_KonnectCompatibility(t *testing.T) {
tests := []struct {
- name string
- content *file.Content
- expected []error
+ name string
+ content *file.Content
+ dumpConfig dump.Config
+ expected []error
}{
{
name: "version invalid",
@@ -26,6 +28,7 @@ func Test_KonnectCompatibility(t *testing.T) {
ControlPlaneName: "s",
},
},
+ dumpConfig: dump.Config{},
expected: []error{
errors.New(errWorkspace),
errors.New(errBadVersion),
@@ -36,6 +39,7 @@ func Test_KonnectCompatibility(t *testing.T) {
content: &file.Content{
FormatVersion: "3.1",
},
+ dumpConfig: dump.Config{},
expected: []error{
errors.New(errKonnect),
},
@@ -60,6 +64,7 @@ func Test_KonnectCompatibility(t *testing.T) {
}},
},
},
+ dumpConfig: dump.Config{},
expected: []error{
fmt.Errorf(errPluginIncompatible, "oauth2"),
},
@@ -95,6 +100,7 @@ func Test_KonnectCompatibility(t *testing.T) {
}},
},
},
+ dumpConfig: dump.Config{},
expected: []error{
fmt.Errorf(errPluginIncompatible, "oauth2"),
fmt.Errorf("[%s] keys are automatically encrypted in Konnect, use the key auth plugin instead", "key-auth-enc"),
@@ -128,15 +134,26 @@ func Test_KonnectCompatibility(t *testing.T) {
},
},
},
+ dumpConfig: dump.Config{},
expected: []error{
fmt.Errorf(errPluginNoCluster, "response-ratelimiting"),
fmt.Errorf("[%s] keys are automatically encrypted in Konnect, use the key auth plugin instead", "key-auth-enc"),
},
},
+ {
+ name: "no konnect info in file, but passed via cli flag",
+ content: &file.Content{
+ FormatVersion: "3.1",
+ },
+ dumpConfig: dump.Config{
+ KonnectControlPlane: "default",
+ },
+ expected: nil,
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- errs := KonnectCompatibility(tt.content)
+ errs := KonnectCompatibility(tt.content, tt.dumpConfig)
assert.Equal(t, tt.expected, errs)
})
}
diff --git a/validate/validate.go b/validate/validate.go
index fe15ad100..256b33718 100644
--- a/validate/validate.go
+++ b/validate/validate.go
@@ -181,6 +181,9 @@ func (v *Validator) Validate(formatVersion semver.Version) []error {
if err := v.entities(v.state.FilterChains, "filter_chains"); err != nil {
allErr = append(allErr, err...)
}
+ if err := v.entities(v.state.Vaults, "vaults"); err != nil {
+ allErr = append(allErr, err...)
+ }
// validate routes format with Kong 3.x
parsed30, err := semver.ParseTolerant(utils.FormatVersion30)