diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c3a2929c8..ce1a36526 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,6 +18,8 @@ jobs: uses: actions/checkout@v3 - name: Setup golangci-lint uses: golangci/golangci-lint-action@v3.6.0 + with: + args: --timeout=30m - name: Verify Codegen run: make verify-codegen - name: Run tests with Coverage diff --git a/.gitignore b/.gitignore index 9b579130f..24f4eddd8 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,11 @@ _testmain.go *.test *.prof +# Apple cruft +.DS_Store + # for this repo only deck dist/ docs/cli-docs/ +.idea/ diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..5c7247b40 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/cmd/file_kong2kic.go b/cmd/file_kong2kic.go new file mode 100644 index 000000000..a17484180 --- /dev/null +++ b/cmd/file_kong2kic.go @@ -0,0 +1,92 @@ +package cmd + +import ( + "fmt" + "log" + "strings" + + "github.com/kong/deck/file" + "github.com/kong/go-apiops/logbasics" + "github.com/spf13/cobra" +) + +var ( + cmdKong2KicInputFilename string + cmdKong2KicOutputFilename string + // cmdKong2KicApi string + cmdKong2KicOutputFormat string + cmdKong2KicManifestStyle string +) + +// Executes the CLI command "kong2kic" +func executeKong2Kic(cmd *cobra.Command, _ []string) error { + var ( + outputContent *file.Content + err error + outputFileFormat file.Format + ) + + verbosity, _ := cmd.Flags().GetInt("verbose") + logbasics.Initialize(log.LstdFlags, verbosity) + + inputContent, err := file.GetContentFromFiles([]string{cmdKong2KicInputFilename}, false) + if err != nil { + return fmt.Errorf("failed reding input file '%s'; %w", cmdKong2KicInputFilename, err) + } + + outputContent = inputContent.DeepCopy() + if strings.ToUpper(cmdKong2KicOutputFormat) == "JSON" && + strings.ToUpper(cmdKong2KicManifestStyle) == "CRD" { + outputFileFormat = file.KICJSONCrd + } else if strings.ToUpper(cmdKong2KicOutputFormat) == "JSON" && + strings.ToUpper(cmdKong2KicManifestStyle) == "ANNOTATION" { + outputFileFormat = file.KICJSONAnnotation + } else if strings.ToUpper(cmdKong2KicOutputFormat) == "YAML" && + strings.ToUpper(cmdKong2KicManifestStyle) == "CRD" { + outputFileFormat = file.KICYAMLCrd + } else if strings.ToUpper(cmdKong2KicOutputFormat) == "YAML" && + strings.ToUpper(cmdKong2KicManifestStyle) == "ANNOTATION" { + outputFileFormat = file.KICYAMLAnnotation + } else { + return fmt.Errorf("invalid combination of output format and manifest style") + } + + err = file.WriteContentToFile(outputContent, cmdKong2KicOutputFilename, outputFileFormat) + + if err != nil { + return fmt.Errorf("failed converting Kong to Ingress '%s'; %w", cmdKong2KicInputFilename, err) + } + + return nil +} + +// +// +// Define the CLI data for the openapi2kong command +// +// + +func newKong2KicCmd() *cobra.Command { + kong2KicCmd := &cobra.Command{ + Use: "kong2kic", + Short: "Convert Kong configuration files to Kong Ingress Controller (KIC) manifests", + Long: `Convert Kong configuration files to Kong Ingress Controller (KIC) manifests. + +Manifests can be generated using annotations in Ingress and Service objects (recommended) or +using the KongIngress CRD. Output in YAML or JSON format.`, + RunE: executeKong2Kic, + Args: cobra.NoArgs, + } + + kong2KicCmd.Flags().StringVarP(&cmdKong2KicInputFilename, "input-file", "i", "-", + "Kong spec file to process. Use - to read from stdin.") + kong2KicCmd.Flags().StringVarP(&cmdKong2KicOutputFilename, "output-file", "o", "-", + "Output file to write. Use - to write to stdout.") + kong2KicCmd.Flags().StringVar(&cmdKong2KicManifestStyle, "style", "annotation", + "Generate manifests with annotations in Service and Ingress, or using the KongIngress CRD: annotation or crd.") + kong2KicCmd.Flags().StringVarP(&cmdKong2KicOutputFormat, "format", "f", "yaml", + "output file format: json or yaml.") + // kong2KicCmd.Flags().StringVarP(&cmdKong2KicApi, "api", "a", "ingress", "[ingress|gateway]") + + return kong2KicCmd +} diff --git a/cmd/root.go b/cmd/root.go index 6397c3031..9a14fe1d7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -235,6 +235,7 @@ It can be used to export, import, or sync entities to Kong.`, fileCmd.AddCommand(newPatchCmd()) fileCmd.AddCommand(newOpenapi2KongCmd()) fileCmd.AddCommand(newFileRenderCmd()) + fileCmd.AddCommand(newKong2KicCmd()) } return rootCmd } diff --git a/convert/convert_test.go b/convert/convert_test.go index b06875592..ca9d17957 100644 --- a/convert/convert_test.go +++ b/convert/convert_test.go @@ -314,6 +314,7 @@ func Test_Convert(t *testing.T) { wantErr: true, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { inputFiles := tt.args.inputFilenames diff --git a/file/kong2kic.go b/file/kong2kic.go new file mode 100644 index 000000000..0412f56b9 --- /dev/null +++ b/file/kong2kic.go @@ -0,0 +1,1185 @@ +package file + +import ( + "encoding/json" + "log" + "strconv" + "strings" + + kicv1 "github.com/kong/kubernetes-ingress-controller/v2/pkg/apis/configuration/v1" + kicv1beta1 "github.com/kong/kubernetes-ingress-controller/v2/pkg/apis/configuration/v1beta1" + k8scorev1 "k8s.io/api/core/v1" + k8snetv1 "k8s.io/api/networking/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// Builder + Director design pattern to create kubernetes manifests based on: +// 1 - Kong custom resource definitions +// 2 - Kong annotations +// 3 - Kubernetes Gateway spec +type IBuilder interface { + buildServices(*Content) + buildRoutes(*Content) + buildGlobalPlugins(*Content) + buildConsumers(*Content) + buildConsumerGroups(*Content) + getContent() *KICContent +} + +const ( + CUSTOMRESOURCE = "CUSTOM_RESOURCE" + ANNOTATIONS = "ANNOTATIONS" + GATEWAY = "GATEWAY" + KICAPIVersion = "configuration.konghq.com/v1" + KongPluginKind = "KongPlugin" + SecretKind = "Secret" + IngressKind = "KongIngress" +) + +func getBuilder(builderType string) IBuilder { + if builderType == CUSTOMRESOURCE { + return newCustomResourceBuilder() + } + + if builderType == ANNOTATIONS { + return newAnnotationsBuilder() + } + + // if builderType == GATEWAY { + // // TODO: implement gateway builder + // } + return nil +} + +type CustomResourceBuilder struct { + kicContent *KICContent +} + +func newCustomResourceBuilder() *CustomResourceBuilder { + return &CustomResourceBuilder{ + kicContent: &KICContent{}, + } +} + +func (b *CustomResourceBuilder) buildServices(content *Content) { + err := populateKICServicesWithCustomResources(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *CustomResourceBuilder) buildRoutes(content *Content) { + err := populateKICIngressesWithCustomResources(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *CustomResourceBuilder) buildGlobalPlugins(content *Content) { + err := populateKICKongClusterPlugins(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *CustomResourceBuilder) buildConsumers(content *Content) { + err := populateKICConsumers(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *CustomResourceBuilder) buildConsumerGroups(content *Content) { + err := populateKICConsumerGroups(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *CustomResourceBuilder) getContent() *KICContent { + return b.kicContent +} + +type AnnotationsBuilder struct { + kicContent *KICContent +} + +func newAnnotationsBuilder() *AnnotationsBuilder { + return &AnnotationsBuilder{ + kicContent: &KICContent{}, + } +} + +func (b *AnnotationsBuilder) buildServices(content *Content) { + err := populateKICServicesWithAnnotations(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *AnnotationsBuilder) buildRoutes(content *Content) { + err := populateKICIngressesWithAnnotations(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *AnnotationsBuilder) buildGlobalPlugins(content *Content) { + err := populateKICKongClusterPlugins(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *AnnotationsBuilder) buildConsumers(content *Content) { + err := populateKICConsumers(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *AnnotationsBuilder) buildConsumerGroups(content *Content) { + err := populateKICConsumerGroups(content, b.kicContent) + if err != nil { + log.Fatal(err) + } +} + +func (b *AnnotationsBuilder) getContent() *KICContent { + return b.kicContent +} + +type Director struct { + builder IBuilder +} + +func newDirector(builder IBuilder) *Director { + return &Director{ + builder: builder, + } +} + +func (d *Director) buildManifests(content *Content) *KICContent { + d.builder.buildServices(content) + d.builder.buildRoutes(content) + d.builder.buildGlobalPlugins(content) + d.builder.buildConsumers(content) + d.builder.buildConsumerGroups(content) + return d.builder.getContent() +} + +//////////////////// +/// End of Builder + Director +//////////////////// + +func MarshalKongToKICYaml(content *Content, builderType string) ([]byte, error) { + kicContent := convertKongToKIC(content, builderType) + return kicContent.marshalKICContentToYaml() +} + +func MarshalKongToKICJson(content *Content, builderType string) ([]byte, error) { + kicContent := convertKongToKIC(content, builderType) + return kicContent.marshalKICContentToJSON() +} + +func convertKongToKIC(content *Content, builderType string) *KICContent { + builder := getBuilder(builderType) + director := newDirector(builder) + return director.buildManifests(content) +} + +///// +// Functions valid for both custom resources and annotations based manifests +///// + +func populateKICKongClusterPlugins(content *Content, file *KICContent) error { + // Global Plugins map to KongClusterPlugins + // iterate content.Plugins and copy them into kicv1.KongPlugin manifests + // add the kicv1.KongPlugin to the KICContent.KongClusterPlugins slice + for _, plugin := range content.Plugins { + var kongPlugin kicv1.KongClusterPlugin + kongPlugin.APIVersion = KICAPIVersion + kongPlugin.Kind = "KongClusterPlugin" + if plugin.InstanceName != nil { + kongPlugin.ObjectMeta.Name = *plugin.InstanceName + } + kongPlugin.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + if plugin.Name != nil { + kongPlugin.PluginName = *plugin.Name + } + + // 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 + file.KongClusterPlugins = append(file.KongClusterPlugins, kongPlugin) + } + return nil +} + +func populateKICConsumers(content *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 = *consumer.Username + kongConsumer.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + kongConsumer.Username = *consumer.Username + if consumer.CustomID != nil { + kongConsumer.CustomID = *consumer.CustomID + } + + populateKICKeyAuthSecrets(&consumer, &kongConsumer, file) + populateKICHMACSecrets(&consumer, &kongConsumer, file) + populateKICJWTAuthSecrets(&consumer, &kongConsumer, file) + populateKICBasicAuthSecrets(&consumer, &kongConsumer, file) + populateKICOAuth2CredSecrets(&consumer, &kongConsumer, file) + 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 + for _, plugin := range consumer.Plugins { + var kongPlugin kicv1.KongPlugin + kongPlugin.APIVersion = KICAPIVersion + kongPlugin.Kind = KongPluginKind + if plugin.InstanceName != nil { + kongPlugin.ObjectMeta.Name = *plugin.InstanceName + } + kongPlugin.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + if plugin.Name != nil { + kongPlugin.PluginName = *plugin.Name + } + + // 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 + file.KongPlugins = append(file.KongPlugins, kongPlugin) + + if kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] == "" { + kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.PluginName + } else { + annotations := kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.PluginName + kongConsumer.ObjectMeta.Annotations["konghq.com/plugins"] = annotations + } + } + + file.KongConsumers = append(file.KongConsumers, kongConsumer) + } + + return nil +} + +func populateKICMTLSAuthSecrets(consumer *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 = strings.ToLower(secretName) + secret.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + secret.StringData = make(map[string]string) + 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 *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 = strings.ToLower(secretName) + secret.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + secret.StringData = make(map[string]string) + + 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 *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 = strings.ToLower(secretName) + secret.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + secret.StringData = make(map[string]string) + 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 *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 = strings.ToLower(secretName) + secret.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + secret.StringData = make(map[string]string) + 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 *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 = strings.ToLower(secretName) + secret.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + secret.StringData = make(map[string]string) + 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 *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 = strings.ToLower(secretName) + secret.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + secret.StringData = make(map[string]string) + 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 *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 = strings.ToLower(secretName) + secret.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + secret.StringData = make(map[string]string) + 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) + + } +} + +func populateKICUpstream(content *Content, service *FService, 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 + kongIngress.ObjectMeta.Name = *service.Name + kongIngress.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + + // 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. + for _, upstream := range content.Upstreams { + if upstream.Name != nil && strings.EqualFold(*upstream.Name, *service.Host) { + 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, + } + } + } + kicContent.KongIngresses = append(kicContent.KongIngresses, kongIngress) + } +} + +func addPluginsToService(service 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 { + kongPlugin.ObjectMeta.Name = *plugin.Name + } + kongPlugin.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + kongPlugin.PluginName = *plugin.Name + + var configJSON apiextensionsv1.JSON + var err error + configJSON.Raw, err = json.Marshal(plugin.Config) + if err != nil { + return err + } + kongPlugin.Config = configJSON + + if k8sService.ObjectMeta.Annotations["konghq.com/plugins"] == "" { + k8sService.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.PluginName + } else { + annotations := k8sService.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.PluginName + k8sService.ObjectMeta.Annotations["konghq.com/plugins"] = annotations + } + + kicContent.KongPlugins = append(kicContent.KongPlugins, kongPlugin) + } + return nil +} + +func addPluginsToRoute(route *FRoute, routeIngresses []k8snetv1.Ingress, kicContent *KICContent) error { + for _, plugin := range route.Plugins { + var kongPlugin kicv1.KongPlugin + kongPlugin.APIVersion = KICAPIVersion + kongPlugin.Kind = KongPluginKind + if plugin.Name != nil { + kongPlugin.ObjectMeta.Name = *plugin.Name + } + kongPlugin.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + kongPlugin.PluginName = *plugin.Name + + var configJSON apiextensionsv1.JSON + var err error + configJSON.Raw, err = json.Marshal(plugin.Config) + if err != nil { + return err + } + kongPlugin.Config = configJSON + + for _, k8sIngress := range routeIngresses { + if k8sIngress.ObjectMeta.Annotations["konghq.com/plugins"] == "" { + k8sIngress.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.PluginName + } else { + annotations := k8sIngress.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.PluginName + k8sIngress.ObjectMeta.Annotations["konghq.com/plugins"] = annotations + } + } + + kicContent.KongPlugins = append(kicContent.KongPlugins, kongPlugin) + } + return nil +} + +func fillIngressHostAndPortSection( + host *string, + service FService, + k8sIngress *k8snetv1.Ingress, + path *string, + pathTypeImplSpecific k8snetv1.PathType, +) { + if host != nil && service.Port != nil { + k8sIngress.Spec.Rules = append(k8sIngress.Spec.Rules, k8snetv1.IngressRule{ + Host: *host, + IngressRuleValue: k8snetv1.IngressRuleValue{ + HTTP: &k8snetv1.HTTPIngressRuleValue{ + Paths: []k8snetv1.HTTPIngressPath{ + { + Path: *path, + PathType: &pathTypeImplSpecific, + Backend: k8snetv1.IngressBackend{ + Service: &k8snetv1.IngressServiceBackend{ + Name: *service.Name, + Port: k8snetv1.ServiceBackendPort{ + Number: int32(*service.Port), + }, + }, + }, + }, + }, + }, + }, + }) + } else if host == nil && service.Port != nil { + k8sIngress.Spec.Rules = append(k8sIngress.Spec.Rules, k8snetv1.IngressRule{ + IngressRuleValue: k8snetv1.IngressRuleValue{ + HTTP: &k8snetv1.HTTPIngressRuleValue{ + Paths: []k8snetv1.HTTPIngressPath{ + { + Path: *path, + PathType: &pathTypeImplSpecific, + Backend: k8snetv1.IngressBackend{ + Service: &k8snetv1.IngressServiceBackend{ + Name: *service.Name, + Port: k8snetv1.ServiceBackendPort{ + Number: int32(*service.Port), + }, + }, + }, + }, + }, + }, + }, + }) + } else if host != nil && service.Port == nil { + k8sIngress.Spec.Rules = append(k8sIngress.Spec.Rules, k8snetv1.IngressRule{ + Host: *host, + IngressRuleValue: k8snetv1.IngressRuleValue{ + HTTP: &k8snetv1.HTTPIngressRuleValue{ + Paths: []k8snetv1.HTTPIngressPath{ + { + Path: *path, + PathType: &pathTypeImplSpecific, + Backend: k8snetv1.IngressBackend{ + Service: &k8snetv1.IngressServiceBackend{ + Name: *service.Name, + }, + }, + }, + }, + }, + }, + }) + } else { + k8sIngress.Spec.Rules = append(k8sIngress.Spec.Rules, k8snetv1.IngressRule{ + IngressRuleValue: k8snetv1.IngressRuleValue{ + HTTP: &k8snetv1.HTTPIngressRuleValue{ + Paths: []k8snetv1.HTTPIngressPath{ + { + Path: *path, + PathType: &pathTypeImplSpecific, + Backend: k8snetv1.IngressBackend{ + Service: &k8snetv1.IngressServiceBackend{ + Name: *service.Name, + }, + }, + }, + }, + }, + }, + }) + } +} + +func populateKICConsumerGroups(content *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 = KICAPIVersion + kongConsumerGroup.Kind = "KongConsumerGroup" + kongConsumerGroup.ObjectMeta.Name = *consumerGroup.Name + kongConsumerGroup.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + kongConsumerGroup.Name = *consumerGroup.Name + + // Iterate over the consumers in consumerGroup and + // find the KongConsumer with the same username in kicContent.KongConsumers + // and add it to the KongConsumerGroup + for _, consumer := range consumerGroup.Consumers { + 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 + + } + } + } + + // for each consumerGroup.plugin, create a KongPlugin and a plugin annotation in the kongConsumerGroup + // to link the plugin + for _, plugin := range consumerGroup.Plugins { + var kongPlugin kicv1.KongPlugin + kongPlugin.APIVersion = KICAPIVersion + kongPlugin.Kind = KongPluginKind + kongPlugin.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + if plugin.Name != nil { + kongPlugin.PluginName = *plugin.Name + } + + // 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) + + if kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] == "" { + kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.PluginName + } else { + annotations := kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] + "," + kongPlugin.PluginName + kongConsumerGroup.ObjectMeta.Annotations["konghq.com/plugins"] = annotations + } + } + + kicContent.KongConsumerGroups = append(kicContent.KongConsumerGroups, kongConsumerGroup) + } + + return nil +} + +///// +// Functions for CUSTOM RESOURCES based manifests +///// + +func populateKICServiceProxyAndUpstreamCustomResources( + content *Content, + service *FService, + k8sservice *k8scorev1.Service, + kicContent *KICContent, +) { + // add Kong specific configuration to the k8s service via a KongIngress resource + + var kongIngress kicv1.KongIngress + kongIngress.APIVersion = KICAPIVersion + kongIngress.Kind = IngressKind + kongIngress.ObjectMeta.Name = *service.Name + kongIngress.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + + // add an annotation to the k8sservice to link this kongIngress to it + k8sservice.ObjectMeta.Annotations["konghq.com/override"] = kongIngress.ObjectMeta.Name + + // proxy attributes from the service to the kongIngress + kongIngress.Proxy = &kicv1.KongIngressService{ + Protocol: service.Protocol, + Path: service.Path, + Retries: service.Retries, + ConnectTimeout: service.ConnectTimeout, + WriteTimeout: service.WriteTimeout, + ReadTimeout: service.ReadTimeout, + } + + // 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. + for _, upstream := range content.Upstreams { + if upstream.Name != nil && strings.EqualFold(*upstream.Name, *service.Host) { + 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, + } + } + } + kicContent.KongIngresses = append(kicContent.KongIngresses, kongIngress) +} + +func populateKICServicesWithCustomResources(content *Content, kicContent *KICContent) error { + // Iterate Kong Services and create k8s Services, + // then create KongIngress resources for Kong Service + // specific configuration and 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 = *service.Name + } else { + log.Println("Service without a name is not recommended") + } + 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 + } + + if service.Port != nil { + sPort := k8scorev1.ServicePort{ + Protocol: protocol, + Port: int32(*service.Port), + TargetPort: intstr.IntOrString{IntVal: int32(*service.Port)}, + } + k8sService.Spec.Ports = append(k8sService.Spec.Ports, sPort) + } + + if service.Name != nil { + k8sService.Spec.Selector = map[string]string{"app": *service.Name} + } else { + log.Println("Service without a name is not recommended") + } + + populateKICServiceProxyAndUpstreamCustomResources(content, &service, &k8sService, kicContent) + + // 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 + } + kicContent.Services = append(kicContent.Services, k8sService) + + } + return nil +} + +func populateKICIngressesWithCustomResources(content *Content, kicContent *KICContent) error { + // Transform routes into k8s Ingress and KongIngress resources + // Assume each pair host/path will get its own ingress manifest + 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 routeIngresses []k8snetv1.Ingress + + // if there are no hosts just use the paths + if len(route.Hosts) == 0 { + routeIngresses = KongRoutePathToIngressPathCustomResources(route, nil, routeIngresses, kicContent, service) + } else { + // iterate over the hosts and paths and create an ingress for each + + for _, host := range route.Hosts { + // create a KongIngress resource and copy route data into it + // add annotation to the ingress to link it to the kongIngress + routeIngresses = KongRoutePathToIngressPathCustomResources(route, host, routeIngresses, kicContent, service) + } + } + // transform the plugin config from map[string]interface{} to apiextensionsv1.JSON + // create a plugins annotation in the routeIngresses to link them to this plugin. + // separate plugins with commas + err := addPluginsToRoute(route, routeIngresses, kicContent) + if err != nil { + return err + } + } + } + return nil +} + +func KongRoutePathToIngressPathCustomResources( + route *FRoute, + host *string, + routeIngresses []k8snetv1.Ingress, + kicContent *KICContent, + service FService, +) []k8snetv1.Ingress { + for _, path := range route.Paths { + var k8sIngress k8snetv1.Ingress + pathTypeImplSpecific := k8snetv1.PathTypeImplementationSpecific + k8sIngress.TypeMeta.APIVersion = "networking.k8s.io/v1" + k8sIngress.TypeMeta.Kind = "Ingress" + k8sIngress.ObjectMeta.Name = *route.Name + ingressClassName := "kong" + k8sIngress.Spec.IngressClassName = &ingressClassName + + // Host and/or Service.Port can be nil. There are 4 possible combinations. + // host == nil && service.Port == nil + fillIngressHostAndPortSection(host, service, &k8sIngress, path, pathTypeImplSpecific) + + // Create a KongIngress resource and copy Kong specific route data into it + var kongIngress kicv1.KongIngress + kongIngress.APIVersion = KICAPIVersion + kongIngress.Kind = IngressKind + kongIngress.ObjectMeta.Name = *route.Name + kongIngress.ObjectMeta.Annotations = map[string]string{"kubernetes.io/ingress.class": "kong"} + + var kongProtocols []*kicv1.KongProtocol + for _, protocol := range route.Protocols { + p := kicv1.KongProtocol(*protocol) + kongProtocols = append(kongProtocols, &p) + } + + kongIngress.Route = &kicv1.KongIngressRoute{ + Methods: route.Methods, + Protocols: kongProtocols, + StripPath: route.StripPath, + PreserveHost: route.PreserveHost, + RegexPriority: route.RegexPriority, + HTTPSRedirectStatusCode: route.HTTPSRedirectStatusCode, + Headers: route.Headers, + PathHandling: route.PathHandling, + SNIs: route.SNIs, + RequestBuffering: route.RequestBuffering, + ResponseBuffering: route.ResponseBuffering, + } + + // add an annotation to the k8sIngress to link it to the kongIngress + k8sIngress.ObjectMeta.Annotations = map[string]string{"konghq.com/override": kongIngress.ObjectMeta.Name} + + routeIngresses = append(routeIngresses, k8sIngress) + + kicContent.Ingresses = append(kicContent.Ingresses, k8sIngress) + kicContent.KongIngresses = append(kicContent.KongIngresses, kongIngress) + } + return routeIngresses +} + +///// +// Functions for ANNOTATION based manifests +///// + +func populateKICServicesWithAnnotations(content *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 = *service.Name + } else { + log.Println("Service without a name is not recommended") + } + 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 + } + + if service.Port != nil { + sPort := k8scorev1.ServicePort{ + Protocol: protocol, + Port: int32(*service.Port), + TargetPort: intstr.IntOrString{IntVal: int32(*service.Port)}, + } + k8sService.Spec.Ports = append(k8sService.Spec.Ports, sPort) + } + + if service.Name != nil { + k8sService.Spec.Selector = map[string]string{"app": *service.Name} + } else { + log.Println("Service without a name is not recommended") + } + + // 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 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) + } + + // 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) + } + + // add konghq.com/protocol annotation if service.Protocol is not nil + if service.Protocol != nil { + k8sService.ObjectMeta.Annotations["konghq.com/protocol"] = *service.Protocol + } + + // add konghq.com/path annotation if service.Path is not nil + if service.Path != nil { + k8sService.ObjectMeta.Annotations["konghq.com/path"] = *service.Path + } + + // 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) + } + + populateKICUpstream(content, &service, &k8sService, kicContent) + + // 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 + } + + kicContent.Services = append(kicContent.Services, k8sService) + + } + return nil +} + +func populateKICIngressesWithAnnotations(content *Content, kicContent *KICContent) error { + // Transform routes into k8s Ingress and KongIngress resources + // Assume each pair host/path will get its own ingress manifest + 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 routeIngresses []k8snetv1.Ingress + + // if there are no hosts just use the paths + if len(route.Hosts) == 0 { + routeIngresses = KongRoutePathToIngressPathAnnotations(route, nil, routeIngresses, kicContent, service) + } else { + // iterate over the hosts and paths and create an ingress for each + + for _, host := range route.Hosts { + // create a KongIngress resource and copy route data into it + // add annotation to the ingress to link it to the kongIngress + routeIngresses = KongRoutePathToIngressPathAnnotations(route, host, routeIngresses, kicContent, service) + } + } + // transform the plugin config from map[string]interface{} to apiextensionsv1.JSON + // create a plugins annotation in the routeIngresses to link them to this plugin. + // separate plugins with commas + err := addPluginsToRoute(route, routeIngresses, kicContent) + if err != nil { + return err + } + } + } + return nil +} + +func KongRoutePathToIngressPathAnnotations( + route *FRoute, + host *string, + routeIngresses []k8snetv1.Ingress, + file *KICContent, + service FService, +) []k8snetv1.Ingress { + for _, path := range route.Paths { + var k8sIngress k8snetv1.Ingress + pathTypeImplSpecific := k8snetv1.PathTypeImplementationSpecific + k8sIngress.TypeMeta.APIVersion = "networking.k8s.io/v1" + k8sIngress.TypeMeta.Kind = "Ingress" + k8sIngress.ObjectMeta.Name = *route.Name + ingressClassName := "kong" + k8sIngress.Spec.IngressClassName = &ingressClassName + k8sIngress.ObjectMeta.Annotations = make(map[string]string) + + // Host and/or Service.Port can be nil. There are 4 possible combinations. + // host == nil && service.Port == nil + fillIngressHostAndPortSection(host, service, &k8sIngress, path, pathTypeImplSpecific) + + // 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) + } + + // 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 + } + + // 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, ",") + } + } + + // 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 + } + + // 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 + } + + // 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) + } + + // 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) + } + + // 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 + } + + routeIngresses = append(routeIngresses, k8sIngress) + + file.Ingresses = append(file.Ingresses, k8sIngress) + } + return routeIngresses +} diff --git a/file/kong2kic_test.go b/file/kong2kic_test.go new file mode 100644 index 000000000..bd2e3fdb0 --- /dev/null +++ b/file/kong2kic_test.go @@ -0,0 +1,210 @@ +package file + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_convertKongGatewayToIngress(t *testing.T) { + type args struct { + inputFilename string + outputFilenameYAMLCRD string + outputFilenameYAMLAnnotation string + outputFilenameJSONCRD string + outputFilenameJSONAnnotation string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "convert one service", + args: args{ + inputFilename: "custom_resources/yaml/1-service/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/1-service/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/1-service/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/1-service/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/1-service/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service and one route", + args: args{ + inputFilename: "custom_resources/yaml/2-service-and-route/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/2-service-and-route/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/2-service-and-route/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/2-service-and-route/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/2-service-and-route/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream data", + args: args{ + inputFilename: "custom_resources/yaml/3-service-and-upstream/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/3-service-and-upstream/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/3-service-and-upstream/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/3-service-and-upstream/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/3-service-and-upstream/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream and route", + args: args{ + inputFilename: "custom_resources/yaml/4-service-route-upstream/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/4-service-route-upstream/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/4-service-route-upstream/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/4-service-route-upstream/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/4-service-route-upstream/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream, route, acl auth plugin", + args: args{ + inputFilename: "custom_resources/yaml/5-service-route-upstream-acl-auth/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/5-service-route-upstream-acl-auth/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/5-service-route-upstream-acl-auth/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/5-service-route-upstream-acl-auth/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/5-service-route-upstream-acl-auth/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream, route, basic auth plugin", + args: args{ + inputFilename: "custom_resources/yaml/6-service-route-upstream-basic-auth/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/6-service-route-upstream-basic-auth/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/6-service-route-upstream-basic-auth/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/6-service-route-upstream-basic-auth/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/6-service-route-upstream-basic-auth/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream, route, jwt auth plugin", + args: args{ + inputFilename: "custom_resources/yaml/7-service-route-upstream-jwt-auth/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/7-service-route-upstream-jwt-auth/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/7-service-route-upstream-jwt-auth/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream, route, key auth plugin", + args: args{ + inputFilename: "custom_resources/yaml/8-service-route-upstream-key-auth/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/8-service-route-upstream-key-auth/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/8-service-route-upstream-key-auth/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/8-service-route-upstream-key-auth/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/8-service-route-upstream-key-auth/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream, route, mtls auth plugin", + args: args{ + inputFilename: "custom_resources/yaml/9-service-route-upstream-mtls-auth/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/9-service-route-upstream-mtls-auth/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/9-service-route-upstream-mtls-auth/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert one service with upstream, route, multiple plugin", + args: args{ + inputFilename: "custom_resources/yaml/10-multiple-plugins-same-route/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/10-multiple-plugins-same-route/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/10-multiple-plugins-same-route/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/10-multiple-plugins-same-route/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/10-multiple-plugins-same-route/output-expected.json", + }, + wantErr: false, + }, + { + name: "convert consumer groups", + args: args{ + inputFilename: "custom_resources/yaml/11-consumer-group/input.yaml", + outputFilenameYAMLCRD: "custom_resources/yaml/11-consumer-group/output-expected.yaml", + outputFilenameJSONCRD: "custom_resources/json/11-consumer-group/output-expected.json", + outputFilenameYAMLAnnotation: "annotations/yaml/11-consumer-group/output-expected.yaml", + outputFilenameJSONAnnotation: "annotations/json/11-consumer-group/output-expected.json", + }, + wantErr: false, + }, + } + for _, tt := range tests { + BaseLocation := "testdata/kong2kic/" + t.Run(tt.name, func(t *testing.T) { + inputContent, err := GetContentFromFiles([]string{BaseLocation + tt.args.inputFilename}, false) + if err != nil { + assert.Fail(t, err.Error()) + } + + output, err := MarshalKongToKICYaml(inputContent, CUSTOMRESOURCE) + if (err != nil) != tt.wantErr { + t.Errorf("KongToKIC() error = %v, wantErr %v", err, tt.wantErr) + } + + if err == nil { + + expected, err := os.ReadFile(BaseLocation + tt.args.outputFilenameYAMLCRD) + if err != nil { + assert.Fail(t, err.Error()) + } + assert.Equal(t, string(expected), string(output)) + } + + output, err = MarshalKongToKICYaml(inputContent, ANNOTATIONS) + if (err != nil) != tt.wantErr { + t.Errorf("KongToKIC() error = %v, wantErr %v", err, tt.wantErr) + } + + if err == nil { + + expected, err := os.ReadFile(BaseLocation + tt.args.outputFilenameYAMLAnnotation) + if err != nil { + assert.Fail(t, err.Error()) + } + assert.Equal(t, string(expected), string(output)) + } + + output, err = MarshalKongToKICJson(inputContent, CUSTOMRESOURCE) + if (err != nil) != tt.wantErr { + t.Errorf("KongToKIC() error = %v, wantErr %v", err, tt.wantErr) + } + + if err == nil { + + expected, err := os.ReadFile(BaseLocation + tt.args.outputFilenameJSONCRD) + if err != nil { + assert.Fail(t, err.Error()) + } + assert.Equal(t, string(expected), string(output)) + } + + output, err = MarshalKongToKICJson(inputContent, ANNOTATIONS) + if (err != nil) != tt.wantErr { + t.Errorf("KongToKIC() error = %v, wantErr %v", err, tt.wantErr) + } + + if err == nil { + + expected, err := os.ReadFile(BaseLocation + tt.args.outputFilenameJSONAnnotation) + if err != nil { + assert.Fail(t, err.Error()) + } + assert.Equal(t, string(expected), string(output)) + } + }) + } +} diff --git a/file/testdata/kong2kic/annotations/json/1-service/input.yaml b/file/testdata/kong2kic/annotations/json/1-service/input.yaml new file mode 100644 index 000000000..2632c2c53 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/1-service/input.yaml @@ -0,0 +1,16 @@ +services: + - name: example-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 \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/1-service/output-expected.json b/file/testdata/kong2kic/annotations/json/1-service/output-expected.json new file mode 100644 index 000000000..69c6f5b8e --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/1-service/output-expected.json @@ -0,0 +1,31 @@ +{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/10-multiple-plugins-same-route/input.yaml b/file/testdata/kong2kic/annotations/json/10-multiple-plugins-same-route/input.yaml new file mode 100644 index 000000000..316ff1b35 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/10-multiple-plugins-same-route/input.yaml @@ -0,0 +1,194 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 + - name: cors + config: + origins: + - example.com + methods: + - GET + - POST + headers: + - Authorization + exposed_headers: + - X-My-Header + max_age: 3600 + credentials: true + - name: file-log + config: + path: /var/log/kong/kong.log + reopen: true + - name: http-log + config: + http_endpoint: http://example.com/logs + method: POST + content_type: application/json + timeout: 10000 + keepalive: 60000 + retry_count: 10 + queue_size: 1000 + - name: ip-restriction + config: + allow: + - 192.168.0.1/24 + deny: + - 192.168.0.2/32 + - name: rate-limiting-advanced + config: + limit: + - 5 + window_size: + - 30 + identifier: consumer + sync_rate: -1 + namespace: example_namespace + strategy: local + hide_client_headers: false + - name: request-termination + config: + status_code: 403 + message: Forbidden + - name: response-ratelimiting + config: + limits: + limit_name: + minute: 10 + policy: local + - name: tcp-log + config: + host: example.com + port: 1234 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/10-multiple-plugins-same-route/output-expected.json b/file/testdata/kong2kic/annotations/json/10-multiple-plugins-same-route/output-expected.json new file mode 100644 index 000000000..8bf257ff6 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/10-multiple-plugins-same-route/output-expected.json @@ -0,0 +1,371 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "aws-lambda", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "aws_key": "my_key", + "aws_region": "us-west-2", + "aws_secret": "my_secret", + "function_name": "my_function" + }, + "plugin": "aws-lambda", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "cors", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "credentials": true, + "exposed_headers": [ + "X-My-Header" + ], + "headers": [ + "Authorization" + ], + "max_age": 3600, + "methods": [ + "GET", + "POST" + ], + "origins": [ + "example.com" + ] + }, + "plugin": "cors", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "file-log", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "path": "/var/log/kong/kong.log", + "reopen": true + }, + "plugin": "file-log", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "http-log", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "content_type": "application/json", + "http_endpoint": "http://example.com/logs", + "keepalive": 60000, + "method": "POST", + "queue_size": 1000, + "retry_count": 10, + "timeout": 10000 + }, + "plugin": "http-log", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "ip-restriction", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "allow": [ + "192.168.0.1/24" + ], + "deny": [ + "192.168.0.2/32" + ] + }, + "plugin": "ip-restriction", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "rate-limiting-advanced", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "hide_client_headers": false, + "identifier": "consumer", + "limit": [ + 5 + ], + "namespace": "example_namespace", + "strategy": "local", + "sync_rate": -1, + "window_size": [ + 30 + ] + }, + "plugin": "rate-limiting-advanced", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "request-termination", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "message": "Forbidden", + "status_code": 403 + }, + "plugin": "request-termination", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "response-ratelimiting", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "limits": { + "limit_name": { + "minute": 10 + } + }, + "policy": "local" + }, + "plugin": "response-ratelimiting", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "tcp-log", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "host": "example.com", + "port": 1234 + }, + "plugin": "tcp-log", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "konghq.com/plugins": "aws-lambda,cors,file-log,http-log,ip-restriction,rate-limiting-advanced,request-termination,response-ratelimiting,tcp-log", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/11-consumer-group/input.yaml b/file/testdata/kong2kic/annotations/json/11-consumer-group/input.yaml new file mode 100644 index 000000000..b57971e33 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/11-consumer-group/input.yaml @@ -0,0 +1,9 @@ +consumer_groups: + - name: example-consumer-group + consumers: + - username: example-user +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/11-consumer-group/output-expected.json b/file/testdata/kong2kic/annotations/json/11-consumer-group/output-expected.json new file mode 100644 index 000000000..3e8cf4b1e --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/11-consumer-group/output-expected.json @@ -0,0 +1,28 @@ +{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "consumerGroups": [ + "example-consumer-group" + ], + "status": {} +}{ + "kind": "KongConsumerGroup", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-consumer-group", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/2-service-and-route/input.yaml b/file/testdata/kong2kic/annotations/json/2-service-and-route/input.yaml new file mode 100644 index 000000000..96ffcce6e --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/2-service-and-route/input.yaml @@ -0,0 +1,44 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/2-service-and-route/output-expected.json b/file/testdata/kong2kic/annotations/json/2-service-and-route/output-expected.json new file mode 100644 index 000000000..62667827e --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/2-service-and-route/output-expected.json @@ -0,0 +1,76 @@ +{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/3-service-and-upstream/input.yaml b/file/testdata/kong2kic/annotations/json/3-service-and-upstream/input.yaml new file mode 100644 index 000000000..0ee8eeadd --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/3-service-and-upstream/input.yaml @@ -0,0 +1,97 @@ +services: + - name: example-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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/annotations/json/3-service-and-upstream/output-expected.json b/file/testdata/kong2kic/annotations/json/3-service-and-upstream/output-expected.json new file mode 100644 index 000000000..f770a97cf --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/3-service-and-upstream/output-expected.json @@ -0,0 +1,131 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/4-service-route-upstream/input.yaml b/file/testdata/kong2kic/annotations/json/4-service-route-upstream/input.yaml new file mode 100644 index 000000000..9e4e5ec86 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/4-service-route-upstream/input.yaml @@ -0,0 +1,125 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/annotations/json/4-service-route-upstream/output-expected.json b/file/testdata/kong2kic/annotations/json/4-service-route-upstream/output-expected.json new file mode 100644 index 000000000..10f4d1792 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/4-service-route-upstream/output-expected.json @@ -0,0 +1,176 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/5-service-route-upstream-acl-auth/input.yaml b/file/testdata/kong2kic/annotations/json/5-service-route-upstream-acl-auth/input.yaml new file mode 100644 index 000000000..e9fb52034 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/5-service-route-upstream-acl-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: acl + config: + allow: + - admin +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + acls: + - group: acl_group + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/5-service-route-upstream-acl-auth/output-expected.json b/file/testdata/kong2kic/annotations/json/5-service-route-upstream-acl-auth/output-expected.json new file mode 100644 index 000000000..3cb78115e --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/5-service-route-upstream-acl-auth/output-expected.json @@ -0,0 +1,224 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "acl", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "allow": [ + "admin" + ] + }, + "plugin": "acl", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "konghq.com/plugins": "acl", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "acl-group-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "group": "acl_group", + "kongCredType": "acl" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "acl-group-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/6-service-route-upstream-basic-auth/input.yaml b/file/testdata/kong2kic/annotations/json/6-service-route-upstream-basic-auth/input.yaml new file mode 100644 index 000000000..163846d4b --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/6-service-route-upstream-basic-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: basic-auth + config: + hide_credentials: false +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + basicauth_credentials: + - username: my_basic_user + password: my_basic_password + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/6-service-route-upstream-basic-auth/output-expected.json b/file/testdata/kong2kic/annotations/json/6-service-route-upstream-basic-auth/output-expected.json new file mode 100644 index 000000000..9842a161a --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/6-service-route-upstream-basic-auth/output-expected.json @@ -0,0 +1,223 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "basic-auth", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "hide_credentials": false + }, + "plugin": "basic-auth", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "konghq.com/plugins": "basic-auth", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "basic-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "kongCredType": "basic-auth", + "password": "my_basic_password", + "username": "my_basic_user" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "basic-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/7-service-route-upstream-jwt-auth/input.yaml b/file/testdata/kong2kic/annotations/json/7-service-route-upstream-jwt-auth/input.yaml new file mode 100644 index 000000000..363f14ea3 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/7-service-route-upstream-jwt-auth/input.yaml @@ -0,0 +1,151 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: jwt + config: + uri_param_names: + - token + claims_to_verify: + - exp + - nbf + key_claim_name: kid + secret_is_base64: false + anonymous: null + run_on_preflight: true + maximum_expiration: 3600 + header_names: + - Authorization +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + jwt_secrets: + - key: my_jwt_secret + algorithm: HS256 + secret: my_secret_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/7-service-route-upstream-jwt-auth/output-expected.json b/file/testdata/kong2kic/annotations/json/7-service-route-upstream-jwt-auth/output-expected.json new file mode 100644 index 000000000..109116be9 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/7-service-route-upstream-jwt-auth/output-expected.json @@ -0,0 +1,238 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "jwt", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "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" + ] + }, + "plugin": "jwt", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "konghq.com/plugins": "jwt", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "jwt-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "algorithm": "HS256", + "key": "my_jwt_secret", + "kongCredType": "jwt", + "secret": "my_secret_key" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "jwt-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/8-service-route-upstream-key-auth/input.yaml b/file/testdata/kong2kic/annotations/json/8-service-route-upstream-key-auth/input.yaml new file mode 100644 index 000000000..754bb520c --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/8-service-route-upstream-key-auth/input.yaml @@ -0,0 +1,142 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: key-auth + config: + hide_credentials: false + key_names: + - apikey + key_in_body: false + run_on_preflight: true +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + keyauth_credentials: + - key: my_api_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/8-service-route-upstream-key-auth/output-expected.json b/file/testdata/kong2kic/annotations/json/8-service-route-upstream-key-auth/output-expected.json new file mode 100644 index 000000000..98a725690 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/8-service-route-upstream-key-auth/output-expected.json @@ -0,0 +1,227 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "key-auth", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "hide_credentials": false, + "key_in_body": false, + "key_names": [ + "apikey" + ], + "run_on_preflight": true + }, + "plugin": "key-auth", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "konghq.com/plugins": "key-auth", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "key-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "key": "my_api_key", + "kongCredType": "key-auth" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "key-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/9-service-route-upstream-mtls-auth/input.yaml b/file/testdata/kong2kic/annotations/json/9-service-route-upstream-mtls-auth/input.yaml new file mode 100644 index 000000000..f12055648 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/9-service-route-upstream-mtls-auth/input.yaml @@ -0,0 +1,140 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: mtls-auth + config: + ca_certificates: + - cce8c384-721f-4f58-85dd-50834e3e733a + skip_consumer_lookup: false + revocation_check_mode: SKIP +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + mtls_auth_credentials: + - id: cce8c384-721f-4f58-85dd-50834e3e733a + subject_name: example-user@example.com \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/json/9-service-route-upstream-mtls-auth/output-expected.json b/file/testdata/kong2kic/annotations/json/9-service-route-upstream-mtls-auth/output-expected.json new file mode 100644 index 000000000..de585a5b6 --- /dev/null +++ b/file/testdata/kong2kic/annotations/json/9-service-route-upstream-mtls-auth/output-expected.json @@ -0,0 +1,228 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "mtls-auth", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "ca_certificates": [ + "cce8c384-721f-4f58-85dd-50834e3e733a" + ], + "revocation_check_mode": "SKIP", + "skip_consumer_lookup": false + }, + "plugin": "mtls-auth", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/headers.x-another-header": "bla", + "konghq.com/headers.x-my-header": "foo,bar", + "konghq.com/https-redirect-status-code": "302", + "konghq.com/methods": "GET,POST", + "konghq.com/plugins": "mtls-auth", + "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" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/connect-timeout": "5000", + "konghq.com/override": "example-service", + "konghq.com/path": "/v1", + "konghq.com/protocol": "http", + "konghq.com/read-timeout": "60000", + "konghq.com/retries": "5", + "konghq.com/write-timeout": "60000" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "mtls-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "id": "cce8c384-721f-4f58-85dd-50834e3e733a", + "kongCredType": "mtls-auth", + "subject_name": "example-user@example.com" + }, + "type": "Opaque" +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "mtls-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/1-service/input.yaml b/file/testdata/kong2kic/annotations/yaml/1-service/input.yaml new file mode 100644 index 000000000..2632c2c53 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/1-service/input.yaml @@ -0,0 +1,16 @@ +services: + - name: example-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 \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/1-service/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/1-service/output-expected.yaml new file mode 100644 index 000000000..9df248f36 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/1-service/output-expected.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/annotations/yaml/10-multiple-plugins-same-route/input.yaml b/file/testdata/kong2kic/annotations/yaml/10-multiple-plugins-same-route/input.yaml new file mode 100644 index 000000000..316ff1b35 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/10-multiple-plugins-same-route/input.yaml @@ -0,0 +1,194 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 + - name: cors + config: + origins: + - example.com + methods: + - GET + - POST + headers: + - Authorization + exposed_headers: + - X-My-Header + max_age: 3600 + credentials: true + - name: file-log + config: + path: /var/log/kong/kong.log + reopen: true + - name: http-log + config: + http_endpoint: http://example.com/logs + method: POST + content_type: application/json + timeout: 10000 + keepalive: 60000 + retry_count: 10 + queue_size: 1000 + - name: ip-restriction + config: + allow: + - 192.168.0.1/24 + deny: + - 192.168.0.2/32 + - name: rate-limiting-advanced + config: + limit: + - 5 + window_size: + - 30 + identifier: consumer + sync_rate: -1 + namespace: example_namespace + strategy: local + hide_client_headers: false + - name: request-termination + config: + status_code: 403 + message: Forbidden + - name: response-ratelimiting + config: + limits: + limit_name: + minute: 10 + policy: local + - name: tcp-log + config: + host: example.com + port: 1234 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/10-multiple-plugins-same-route/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/10-multiple-plugins-same-route/output-expected.yaml new file mode 100644 index 000000000..1d6ae5982 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/10-multiple-plugins-same-route/output-expected.yaml @@ -0,0 +1,292 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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: + 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 + creationTimestamp: null + name: aws-lambda +plugin: aws-lambda +status: {} +--- +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 + creationTimestamp: null + name: cors +plugin: cors +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + path: /var/log/kong/kong.log + reopen: true +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: file-log +plugin: file-log +status: {} +--- +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 + creationTimestamp: null + name: http-log +plugin: http-log +status: {} +--- +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 + creationTimestamp: null + name: ip-restriction +plugin: ip-restriction +status: {} +--- +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 + creationTimestamp: null + name: rate-limiting-advanced +plugin: rate-limiting-advanced +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + message: Forbidden + status_code: 403 +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: request-termination +plugin: request-termination +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + limits: + limit_name: + minute: 10 + policy: local +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: response-ratelimiting +plugin: response-ratelimiting +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + host: example.com + port: 1234 +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: tcp-log +plugin: tcp-log +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + konghq.com/plugins: aws-lambda,cors,file-log,http-log,ip-restriction,rate-limiting-advanced,request-termination,response-ratelimiting,tcp-log + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: configuration.konghq.com/v1 +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/annotations/yaml/11-consumer-group/input.yaml b/file/testdata/kong2kic/annotations/yaml/11-consumer-group/input.yaml new file mode 100644 index 000000000..b57971e33 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/11-consumer-group/input.yaml @@ -0,0 +1,9 @@ +consumer_groups: + - name: example-consumer-group + consumers: + - username: example-user +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/11-consumer-group/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/11-consumer-group/output-expected.yaml new file mode 100644 index 000000000..19827ed76 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/11-consumer-group/output-expected.yaml @@ -0,0 +1,22 @@ +apiVersion: configuration.konghq.com/v1 +consumerGroups: +- example-consumer-group +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- +apiVersion: configuration.konghq.com/v1 +kind: KongConsumerGroup +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-consumer-group +status: {} +--- diff --git a/file/testdata/kong2kic/annotations/yaml/2-service-and-route/input.yaml b/file/testdata/kong2kic/annotations/yaml/2-service-and-route/input.yaml new file mode 100644 index 000000000..96ffcce6e --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/2-service-and-route/input.yaml @@ -0,0 +1,44 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/2-service-and-route/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/2-service-and-route/output-expected.yaml new file mode 100644 index 000000000..a69aee1d9 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/2-service-and-route/output-expected.yaml @@ -0,0 +1,53 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/annotations/yaml/3-service-and-upstream/input.yaml b/file/testdata/kong2kic/annotations/yaml/3-service-and-upstream/input.yaml new file mode 100644 index 000000000..0ee8eeadd --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/3-service-and-upstream/input.yaml @@ -0,0 +1,97 @@ +services: + - name: example-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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/annotations/yaml/3-service-and-upstream/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/3-service-and-upstream/output-expected.yaml new file mode 100644 index 000000000..017f8f2d3 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/3-service-and-upstream/output-expected.yaml @@ -0,0 +1,105 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/annotations/yaml/4-service-route-upstream/input.yaml b/file/testdata/kong2kic/annotations/yaml/4-service-route-upstream/input.yaml new file mode 100644 index 000000000..9e4e5ec86 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/4-service-route-upstream/input.yaml @@ -0,0 +1,125 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/annotations/yaml/4-service-route-upstream/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/4-service-route-upstream/output-expected.yaml new file mode 100644 index 000000000..9baddd252 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/4-service-route-upstream/output-expected.yaml @@ -0,0 +1,136 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/annotations/yaml/5-service-route-upstream-acl-auth/input.yaml b/file/testdata/kong2kic/annotations/yaml/5-service-route-upstream-acl-auth/input.yaml new file mode 100644 index 000000000..e9fb52034 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/5-service-route-upstream-acl-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: acl + config: + allow: + - admin +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + acls: + - group: acl_group + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/5-service-route-upstream-acl-auth/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/5-service-route-upstream-acl-auth/output-expected.yaml new file mode 100644 index 000000000..dc025e73b --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/5-service-route-upstream-acl-auth/output-expected.yaml @@ -0,0 +1,174 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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: + allow: + - admin +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: acl +plugin: acl +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + konghq.com/plugins: acl + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: acl-group-example-user +stringData: + group: acl_group + kongCredType: acl +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- acl-group-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/annotations/yaml/6-service-route-upstream-basic-auth/input.yaml b/file/testdata/kong2kic/annotations/yaml/6-service-route-upstream-basic-auth/input.yaml new file mode 100644 index 000000000..163846d4b --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/6-service-route-upstream-basic-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: basic-auth + config: + hide_credentials: false +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + basicauth_credentials: + - username: my_basic_user + password: my_basic_password + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/6-service-route-upstream-basic-auth/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/6-service-route-upstream-basic-auth/output-expected.yaml new file mode 100644 index 000000000..918b21b62 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/6-service-route-upstream-basic-auth/output-expected.yaml @@ -0,0 +1,174 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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_credentials: false +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: basic-auth +plugin: basic-auth +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + konghq.com/plugins: basic-auth + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: basic-auth-example-user +stringData: + kongCredType: basic-auth + password: my_basic_password + username: my_basic_user +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- basic-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/annotations/yaml/7-service-route-upstream-jwt-auth/input.yaml b/file/testdata/kong2kic/annotations/yaml/7-service-route-upstream-jwt-auth/input.yaml new file mode 100644 index 000000000..363f14ea3 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/7-service-route-upstream-jwt-auth/input.yaml @@ -0,0 +1,151 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: jwt + config: + uri_param_names: + - token + claims_to_verify: + - exp + - nbf + key_claim_name: kid + secret_is_base64: false + anonymous: null + run_on_preflight: true + maximum_expiration: 3600 + header_names: + - Authorization +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + jwt_secrets: + - key: my_jwt_secret + algorithm: HS256 + secret: my_secret_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml new file mode 100644 index 000000000..56265f57b --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml @@ -0,0 +1,186 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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: + 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 + creationTimestamp: null + name: jwt +plugin: jwt +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + konghq.com/plugins: jwt + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: jwt-auth-example-user +stringData: + algorithm: HS256 + key: my_jwt_secret + kongCredType: jwt + secret: my_secret_key +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- jwt-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/annotations/yaml/8-service-route-upstream-key-auth/input.yaml b/file/testdata/kong2kic/annotations/yaml/8-service-route-upstream-key-auth/input.yaml new file mode 100644 index 000000000..754bb520c --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/8-service-route-upstream-key-auth/input.yaml @@ -0,0 +1,142 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: key-auth + config: + hide_credentials: false + key_names: + - apikey + key_in_body: false + run_on_preflight: true +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + keyauth_credentials: + - key: my_api_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/8-service-route-upstream-key-auth/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/8-service-route-upstream-key-auth/output-expected.yaml new file mode 100644 index 000000000..076148230 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/8-service-route-upstream-key-auth/output-expected.yaml @@ -0,0 +1,177 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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_credentials: false + key_in_body: false + key_names: + - apikey + run_on_preflight: true +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: key-auth +plugin: key-auth +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + konghq.com/plugins: key-auth + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: key-auth-example-user +stringData: + key: my_api_key + kongCredType: key-auth +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- key-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/annotations/yaml/9-service-route-upstream-mtls-auth/input.yaml b/file/testdata/kong2kic/annotations/yaml/9-service-route-upstream-mtls-auth/input.yaml new file mode 100644 index 000000000..f12055648 --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/9-service-route-upstream-mtls-auth/input.yaml @@ -0,0 +1,140 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: mtls-auth + config: + ca_certificates: + - cce8c384-721f-4f58-85dd-50834e3e733a + skip_consumer_lookup: false + revocation_check_mode: SKIP +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + mtls_auth_credentials: + - id: cce8c384-721f-4f58-85dd-50834e3e733a + subject_name: example-user@example.com \ No newline at end of file diff --git a/file/testdata/kong2kic/annotations/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml b/file/testdata/kong2kic/annotations/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml new file mode 100644 index 000000000..640e3615b --- /dev/null +++ b/file/testdata/kong2kic/annotations/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml @@ -0,0 +1,178 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +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: + ca_certificates: + - cce8c384-721f-4f58-85dd-50834e3e733a + revocation_check_mode: SKIP + skip_consumer_lookup: false +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: mtls-auth +plugin: mtls-auth +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/headers.x-another-header: bla + konghq.com/headers.x-my-header: foo,bar + konghq.com/https-redirect-status-code: "302" + konghq.com/methods: GET,POST + konghq.com/plugins: mtls-auth + 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" + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/connect-timeout: "5000" + konghq.com/override: example-service + konghq.com/path: /v1 + konghq.com/protocol: http + konghq.com/read-timeout: "60000" + konghq.com/retries: "5" + konghq.com/write-timeout: "60000" + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + 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: +- mtls-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/custom_resources/json/1-service/input.yaml b/file/testdata/kong2kic/custom_resources/json/1-service/input.yaml new file mode 100644 index 000000000..2632c2c53 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/1-service/input.yaml @@ -0,0 +1,16 @@ +services: + - name: example-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 \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/1-service/output-expected.json b/file/testdata/kong2kic/custom_resources/json/1-service/output-expected.json new file mode 100644 index 000000000..db9c52653 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/1-service/output-expected.json @@ -0,0 +1,44 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/10-multiple-plugins-same-route/input.yaml b/file/testdata/kong2kic/custom_resources/json/10-multiple-plugins-same-route/input.yaml new file mode 100644 index 000000000..316ff1b35 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/10-multiple-plugins-same-route/input.yaml @@ -0,0 +1,194 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 + - name: cors + config: + origins: + - example.com + methods: + - GET + - POST + headers: + - Authorization + exposed_headers: + - X-My-Header + max_age: 3600 + credentials: true + - name: file-log + config: + path: /var/log/kong/kong.log + reopen: true + - name: http-log + config: + http_endpoint: http://example.com/logs + method: POST + content_type: application/json + timeout: 10000 + keepalive: 60000 + retry_count: 10 + queue_size: 1000 + - name: ip-restriction + config: + allow: + - 192.168.0.1/24 + deny: + - 192.168.0.2/32 + - name: rate-limiting-advanced + config: + limit: + - 5 + window_size: + - 30 + identifier: consumer + sync_rate: -1 + namespace: example_namespace + strategy: local + hide_client_headers: false + - name: request-termination + config: + status_code: 403 + message: Forbidden + - name: response-ratelimiting + config: + limits: + limit_name: + minute: 10 + policy: local + - name: tcp-log + config: + host: example.com + port: 1234 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/10-multiple-plugins-same-route/output-expected.json b/file/testdata/kong2kic/custom_resources/json/10-multiple-plugins-same-route/output-expected.json new file mode 100644 index 000000000..152f3b8ae --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/10-multiple-plugins-same-route/output-expected.json @@ -0,0 +1,401 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "aws-lambda", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "aws_key": "my_key", + "aws_region": "us-west-2", + "aws_secret": "my_secret", + "function_name": "my_function" + }, + "plugin": "aws-lambda", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "cors", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "credentials": true, + "exposed_headers": [ + "X-My-Header" + ], + "headers": [ + "Authorization" + ], + "max_age": 3600, + "methods": [ + "GET", + "POST" + ], + "origins": [ + "example.com" + ] + }, + "plugin": "cors", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "file-log", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "path": "/var/log/kong/kong.log", + "reopen": true + }, + "plugin": "file-log", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "http-log", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "content_type": "application/json", + "http_endpoint": "http://example.com/logs", + "keepalive": 60000, + "method": "POST", + "queue_size": 1000, + "retry_count": 10, + "timeout": 10000 + }, + "plugin": "http-log", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "ip-restriction", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "allow": [ + "192.168.0.1/24" + ], + "deny": [ + "192.168.0.2/32" + ] + }, + "plugin": "ip-restriction", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "rate-limiting-advanced", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "hide_client_headers": false, + "identifier": "consumer", + "limit": [ + 5 + ], + "namespace": "example_namespace", + "strategy": "local", + "sync_rate": -1, + "window_size": [ + 30 + ] + }, + "plugin": "rate-limiting-advanced", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "request-termination", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "message": "Forbidden", + "status_code": 403 + }, + "plugin": "request-termination", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "response-ratelimiting", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "limits": { + "limit_name": { + "minute": 10 + } + }, + "policy": "local" + }, + "plugin": "response-ratelimiting", + "status": {} +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "tcp-log", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "host": "example.com", + "port": 1234 + }, + "plugin": "tcp-log", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route", + "konghq.com/plugins": "aws-lambda,cors,file-log,http-log,ip-restriction,rate-limiting-advanced,request-termination,response-ratelimiting,tcp-log" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/11-consumer-group/input.yaml b/file/testdata/kong2kic/custom_resources/json/11-consumer-group/input.yaml new file mode 100644 index 000000000..b57971e33 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/11-consumer-group/input.yaml @@ -0,0 +1,9 @@ +consumer_groups: + - name: example-consumer-group + consumers: + - username: example-user +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/11-consumer-group/output-expected.json b/file/testdata/kong2kic/custom_resources/json/11-consumer-group/output-expected.json new file mode 100644 index 000000000..3e8cf4b1e --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/11-consumer-group/output-expected.json @@ -0,0 +1,28 @@ +{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "consumerGroups": [ + "example-consumer-group" + ], + "status": {} +}{ + "kind": "KongConsumerGroup", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-consumer-group", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/2-service-and-route/input.yaml b/file/testdata/kong2kic/custom_resources/json/2-service-and-route/input.yaml new file mode 100644 index 000000000..96ffcce6e --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/2-service-and-route/input.yaml @@ -0,0 +1,44 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/2-service-and-route/output-expected.json b/file/testdata/kong2kic/custom_resources/json/2-service-and-route/output-expected.json new file mode 100644 index 000000000..86ae5d069 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/2-service-and-route/output-expected.json @@ -0,0 +1,117 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/3-service-and-upstream/input.yaml b/file/testdata/kong2kic/custom_resources/json/3-service-and-upstream/input.yaml new file mode 100644 index 000000000..0ee8eeadd --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/3-service-and-upstream/input.yaml @@ -0,0 +1,97 @@ +services: + - name: example-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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/custom_resources/json/3-service-and-upstream/output-expected.json b/file/testdata/kong2kic/custom_resources/json/3-service-and-upstream/output-expected.json new file mode 100644 index 000000000..f226a23db --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/3-service-and-upstream/output-expected.json @@ -0,0 +1,133 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/4-service-route-upstream/input.yaml b/file/testdata/kong2kic/custom_resources/json/4-service-route-upstream/input.yaml new file mode 100644 index 000000000..9e4e5ec86 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/4-service-route-upstream/input.yaml @@ -0,0 +1,125 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/custom_resources/json/4-service-route-upstream/output-expected.json b/file/testdata/kong2kic/custom_resources/json/4-service-route-upstream/output-expected.json new file mode 100644 index 000000000..23d2b86d8 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/4-service-route-upstream/output-expected.json @@ -0,0 +1,206 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/5-service-route-upstream-acl-auth/input.yaml b/file/testdata/kong2kic/custom_resources/json/5-service-route-upstream-acl-auth/input.yaml new file mode 100644 index 000000000..e9fb52034 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/5-service-route-upstream-acl-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: acl + config: + allow: + - admin +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + acls: + - group: acl_group + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/5-service-route-upstream-acl-auth/output-expected.json b/file/testdata/kong2kic/custom_resources/json/5-service-route-upstream-acl-auth/output-expected.json new file mode 100644 index 000000000..e2e70f0b5 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/5-service-route-upstream-acl-auth/output-expected.json @@ -0,0 +1,254 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "acl", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "allow": [ + "admin" + ] + }, + "plugin": "acl", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route", + "konghq.com/plugins": "acl" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "acl-group-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "group": "acl_group", + "kongCredType": "acl" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "acl-group-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/6-service-route-upstream-basic-auth/input.yaml b/file/testdata/kong2kic/custom_resources/json/6-service-route-upstream-basic-auth/input.yaml new file mode 100644 index 000000000..163846d4b --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/6-service-route-upstream-basic-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: basic-auth + config: + hide_credentials: false +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + basicauth_credentials: + - username: my_basic_user + password: my_basic_password + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/6-service-route-upstream-basic-auth/output-expected.json b/file/testdata/kong2kic/custom_resources/json/6-service-route-upstream-basic-auth/output-expected.json new file mode 100644 index 000000000..0701fbb57 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/6-service-route-upstream-basic-auth/output-expected.json @@ -0,0 +1,253 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "basic-auth", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "hide_credentials": false + }, + "plugin": "basic-auth", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route", + "konghq.com/plugins": "basic-auth" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "basic-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "kongCredType": "basic-auth", + "password": "my_basic_password", + "username": "my_basic_user" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "basic-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/7-service-route-upstream-jwt-auth/input.yaml b/file/testdata/kong2kic/custom_resources/json/7-service-route-upstream-jwt-auth/input.yaml new file mode 100644 index 000000000..363f14ea3 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/7-service-route-upstream-jwt-auth/input.yaml @@ -0,0 +1,151 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: jwt + config: + uri_param_names: + - token + claims_to_verify: + - exp + - nbf + key_claim_name: kid + secret_is_base64: false + anonymous: null + run_on_preflight: true + maximum_expiration: 3600 + header_names: + - Authorization +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + jwt_secrets: + - key: my_jwt_secret + algorithm: HS256 + secret: my_secret_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/7-service-route-upstream-jwt-auth/output-expected.json b/file/testdata/kong2kic/custom_resources/json/7-service-route-upstream-jwt-auth/output-expected.json new file mode 100644 index 000000000..035d62dbf --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/7-service-route-upstream-jwt-auth/output-expected.json @@ -0,0 +1,268 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "jwt", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "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" + ] + }, + "plugin": "jwt", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route", + "konghq.com/plugins": "jwt" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "jwt-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "algorithm": "HS256", + "key": "my_jwt_secret", + "kongCredType": "jwt", + "secret": "my_secret_key" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "jwt-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/8-service-route-upstream-key-auth/input.yaml b/file/testdata/kong2kic/custom_resources/json/8-service-route-upstream-key-auth/input.yaml new file mode 100644 index 000000000..754bb520c --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/8-service-route-upstream-key-auth/input.yaml @@ -0,0 +1,142 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: key-auth + config: + hide_credentials: false + key_names: + - apikey + key_in_body: false + run_on_preflight: true +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + keyauth_credentials: + - key: my_api_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/8-service-route-upstream-key-auth/output-expected.json b/file/testdata/kong2kic/custom_resources/json/8-service-route-upstream-key-auth/output-expected.json new file mode 100644 index 000000000..59f3c4dc2 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/8-service-route-upstream-key-auth/output-expected.json @@ -0,0 +1,257 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "key-auth", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "hide_credentials": false, + "key_in_body": false, + "key_names": [ + "apikey" + ], + "run_on_preflight": true + }, + "plugin": "key-auth", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route", + "konghq.com/plugins": "key-auth" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "key-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "key": "my_api_key", + "kongCredType": "key-auth" + } +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "key-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/9-service-route-upstream-mtls-auth/input.yaml b/file/testdata/kong2kic/custom_resources/json/9-service-route-upstream-mtls-auth/input.yaml new file mode 100644 index 000000000..f12055648 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/9-service-route-upstream-mtls-auth/input.yaml @@ -0,0 +1,140 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: mtls-auth + config: + ca_certificates: + - cce8c384-721f-4f58-85dd-50834e3e733a + skip_consumer_lookup: false + revocation_check_mode: SKIP +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + mtls_auth_credentials: + - id: cce8c384-721f-4f58-85dd-50834e3e733a + subject_name: example-user@example.com \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/json/9-service-route-upstream-mtls-auth/output-expected.json b/file/testdata/kong2kic/custom_resources/json/9-service-route-upstream-mtls-auth/output-expected.json new file mode 100644 index 000000000..22c01e94f --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/json/9-service-route-upstream-mtls-auth/output-expected.json @@ -0,0 +1,258 @@ +{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "upstream": { + "host_header": "example.com", + "algorithm": "round-robin", + "slots": 10000, + "healthchecks": { + "active": { + "concurrency": 10, + "healthy": { + "http_statuses": [ + 200, + 302 + ], + "interval": 0, + "successes": 0 + }, + "http_path": "/", + "https_sni": "example.com", + "https_verify_certificate": true, + "type": "http", + "timeout": 1, + "unhealthy": { + "http_failures": 0, + "http_statuses": [ + 429, + 404, + 500, + 501, + 502, + 503, + 504, + 505 + ], + "tcp_failures": 0, + "timeouts": 0, + "interval": 0 + }, + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + } + }, + "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 + }, + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/" + }, + "proxy": { + "protocol": "http", + "path": "/v1", + "retries": 5, + "connect_timeout": 5000, + "read_timeout": 60000, + "write_timeout": 60000 + } +}{ + "kind": "KongIngress", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "route": { + "methods": [ + "GET", + "POST" + ], + "headers": { + "x-another-header": [ + "bla" + ], + "x-my-header": [ + "foo", + "bar" + ] + }, + "protocols": [ + "http", + "https" + ], + "regex_priority": 1, + "strip_path": false, + "preserve_host": true, + "https_redirect_status_code": 302, + "snis": [ + "example.com" + ] + } +}{ + "kind": "KongPlugin", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "mtls-auth", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "config": { + "ca_certificates": [ + "cce8c384-721f-4f58-85dd-50834e3e733a" + ], + "revocation_check_mode": "SKIP", + "skip_consumer_lookup": false + }, + "plugin": "mtls-auth", + "status": {} +}{ + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example-route", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-route", + "konghq.com/plugins": "mtls-auth" + } + }, + "spec": { + "ingressClassName": "kong", + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/v1/example", + "pathType": "ImplementationSpecific", + "backend": { + "service": { + "name": "example-service", + "port": { + "number": 80 + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "example-service", + "creationTimestamp": null, + "annotations": { + "konghq.com/override": "example-service" + } + }, + "spec": { + "ports": [ + { + "protocol": "TCP", + "port": 80, + "targetPort": 80 + } + ], + "selector": { + "app": "example-service" + } + }, + "status": { + "loadBalancer": {} + } +}{ + "kind": "Secret", + "apiVersion": "v1", + "metadata": { + "name": "mtls-auth-example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "stringData": { + "id": "cce8c384-721f-4f58-85dd-50834e3e733a", + "kongCredType": "mtls-auth", + "subject_name": "example-user@example.com" + }, + "type": "Opaque" +}{ + "kind": "KongConsumer", + "apiVersion": "configuration.konghq.com/v1", + "metadata": { + "name": "example-user", + "creationTimestamp": null, + "annotations": { + "kubernetes.io/ingress.class": "kong" + } + }, + "username": "example-user", + "custom_id": "1234567890", + "credentials": [ + "mtls-auth-example-user" + ], + "status": {} +} \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/1-service/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/1-service/input.yaml new file mode 100644 index 000000000..2632c2c53 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/1-service/input.yaml @@ -0,0 +1,16 @@ +services: + - name: example-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 \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/1-service/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/1-service/output-expected.yaml new file mode 100644 index 000000000..14aad8740 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/1-service/output-expected.yaml @@ -0,0 +1,32 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/10-multiple-plugins-same-route/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/10-multiple-plugins-same-route/input.yaml new file mode 100644 index 000000000..316ff1b35 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/10-multiple-plugins-same-route/input.yaml @@ -0,0 +1,194 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 + - name: cors + config: + origins: + - example.com + methods: + - GET + - POST + headers: + - Authorization + exposed_headers: + - X-My-Header + max_age: 3600 + credentials: true + - name: file-log + config: + path: /var/log/kong/kong.log + reopen: true + - name: http-log + config: + http_endpoint: http://example.com/logs + method: POST + content_type: application/json + timeout: 10000 + keepalive: 60000 + retry_count: 10 + queue_size: 1000 + - name: ip-restriction + config: + allow: + - 192.168.0.1/24 + deny: + - 192.168.0.2/32 + - name: rate-limiting-advanced + config: + limit: + - 5 + window_size: + - 30 + identifier: consumer + sync_rate: -1 + namespace: example_namespace + strategy: local + hide_client_headers: false + - name: request-termination + config: + status_code: 403 + message: Forbidden + - name: response-ratelimiting + config: + limits: + limit_name: + minute: 10 + policy: local + - name: tcp-log + config: + host: example.com + port: 1234 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/10-multiple-plugins-same-route/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/10-multiple-plugins-same-route/output-expected.yaml new file mode 100644 index 000000000..b951ff177 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/10-multiple-plugins-same-route/output-expected.yaml @@ -0,0 +1,312 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +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 + creationTimestamp: null + name: aws-lambda +plugin: aws-lambda +status: {} +--- +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 + creationTimestamp: null + name: cors +plugin: cors +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + path: /var/log/kong/kong.log + reopen: true +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: file-log +plugin: file-log +status: {} +--- +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 + creationTimestamp: null + name: http-log +plugin: http-log +status: {} +--- +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 + creationTimestamp: null + name: ip-restriction +plugin: ip-restriction +status: {} +--- +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 + creationTimestamp: null + name: rate-limiting-advanced +plugin: rate-limiting-advanced +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + message: Forbidden + status_code: 403 +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: request-termination +plugin: request-termination +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + limits: + limit_name: + minute: 10 + policy: local +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: response-ratelimiting +plugin: response-ratelimiting +status: {} +--- +apiVersion: configuration.konghq.com/v1 +config: + host: example.com + port: 1234 +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: tcp-log +plugin: tcp-log +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + konghq.com/plugins: aws-lambda,cors,file-log,http-log,ip-restriction,rate-limiting-advanced,request-termination,response-ratelimiting,tcp-log + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: configuration.konghq.com/v1 +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/11-consumer-group/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/11-consumer-group/input.yaml new file mode 100644 index 000000000..b57971e33 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/11-consumer-group/input.yaml @@ -0,0 +1,9 @@ +consumer_groups: + - name: example-consumer-group + consumers: + - username: example-user +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/11-consumer-group/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/11-consumer-group/output-expected.yaml new file mode 100644 index 000000000..19827ed76 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/11-consumer-group/output-expected.yaml @@ -0,0 +1,22 @@ +apiVersion: configuration.konghq.com/v1 +consumerGroups: +- example-consumer-group +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- +apiVersion: configuration.konghq.com/v1 +kind: KongConsumerGroup +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-consumer-group +status: {} +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/2-service-and-route/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/2-service-and-route/input.yaml new file mode 100644 index 000000000..96ffcce6e --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/2-service-and-route/input.yaml @@ -0,0 +1,44 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/2-service-and-route/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/2-service-and-route/output-expected.yaml new file mode 100644 index 000000000..9d64b3a1d --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/2-service-and-route/output-expected.yaml @@ -0,0 +1,82 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +--- +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/3-service-and-upstream/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/3-service-and-upstream/input.yaml new file mode 100644 index 000000000..0ee8eeadd --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/3-service-and-upstream/input.yaml @@ -0,0 +1,97 @@ +services: + - name: example-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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/custom_resources/yaml/3-service-and-upstream/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/3-service-and-upstream/output-expected.yaml new file mode 100644 index 000000000..f53030b9c --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/3-service-and-upstream/output-expected.yaml @@ -0,0 +1,106 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/4-service-route-upstream/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/4-service-route-upstream/input.yaml new file mode 100644 index 000000000..9e4e5ec86 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/4-service-route-upstream/input.yaml @@ -0,0 +1,125 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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 +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false diff --git a/file/testdata/kong2kic/custom_resources/yaml/4-service-route-upstream/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/4-service-route-upstream/output-expected.yaml new file mode 100644 index 000000000..7092e95a8 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/4-service-route-upstream/output-expected.yaml @@ -0,0 +1,156 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/5-service-route-upstream-acl-auth/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/5-service-route-upstream-acl-auth/input.yaml new file mode 100644 index 000000000..e9fb52034 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/5-service-route-upstream-acl-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: acl + config: + allow: + - admin +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + acls: + - group: acl_group + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/5-service-route-upstream-acl-auth/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/5-service-route-upstream-acl-auth/output-expected.yaml new file mode 100644 index 000000000..e9d346443 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/5-service-route-upstream-acl-auth/output-expected.yaml @@ -0,0 +1,194 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +apiVersion: configuration.konghq.com/v1 +config: + allow: + - admin +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: acl +plugin: acl +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + konghq.com/plugins: acl + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: acl-group-example-user +stringData: + group: acl_group + kongCredType: acl +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- acl-group-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/6-service-route-upstream-basic-auth/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/6-service-route-upstream-basic-auth/input.yaml new file mode 100644 index 000000000..163846d4b --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/6-service-route-upstream-basic-auth/input.yaml @@ -0,0 +1,139 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: basic-auth + config: + hide_credentials: false +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + basicauth_credentials: + - username: my_basic_user + password: my_basic_password + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/6-service-route-upstream-basic-auth/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/6-service-route-upstream-basic-auth/output-expected.yaml new file mode 100644 index 000000000..023b013c4 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/6-service-route-upstream-basic-auth/output-expected.yaml @@ -0,0 +1,194 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +apiVersion: configuration.konghq.com/v1 +config: + hide_credentials: false +kind: KongPlugin +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: basic-auth +plugin: basic-auth +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + konghq.com/plugins: basic-auth + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: basic-auth-example-user +stringData: + kongCredType: basic-auth + password: my_basic_password + username: my_basic_user +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- basic-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/7-service-route-upstream-jwt-auth/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/7-service-route-upstream-jwt-auth/input.yaml new file mode 100644 index 000000000..363f14ea3 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/7-service-route-upstream-jwt-auth/input.yaml @@ -0,0 +1,151 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: jwt + config: + uri_param_names: + - token + claims_to_verify: + - exp + - nbf + key_claim_name: kid + secret_is_base64: false + anonymous: null + run_on_preflight: true + maximum_expiration: 3600 + header_names: + - Authorization +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + jwt_secrets: + - key: my_jwt_secret + algorithm: HS256 + secret: my_secret_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml new file mode 100644 index 000000000..f0861819f --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/7-service-route-upstream-jwt-auth/output-expected.yaml @@ -0,0 +1,206 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +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 + creationTimestamp: null + name: jwt +plugin: jwt +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + konghq.com/plugins: jwt + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: jwt-auth-example-user +stringData: + algorithm: HS256 + key: my_jwt_secret + kongCredType: jwt + secret: my_secret_key +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- jwt-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/8-service-route-upstream-key-auth/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/8-service-route-upstream-key-auth/input.yaml new file mode 100644 index 000000000..754bb520c --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/8-service-route-upstream-key-auth/input.yaml @@ -0,0 +1,142 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: key-auth + config: + hide_credentials: false + key_names: + - apikey + key_in_body: false + run_on_preflight: true +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + keyauth_credentials: + - key: my_api_key + tags: + - internal \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/8-service-route-upstream-key-auth/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/8-service-route-upstream-key-auth/output-expected.yaml new file mode 100644 index 000000000..c28d85653 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/8-service-route-upstream-key-auth/output-expected.yaml @@ -0,0 +1,197 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +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 + creationTimestamp: null + name: key-auth +plugin: key-auth +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + konghq.com/plugins: key-auth + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: key-auth-example-user +stringData: + key: my_api_key + kongCredType: key-auth +--- +apiVersion: configuration.konghq.com/v1 +credentials: +- key-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/testdata/kong2kic/custom_resources/yaml/9-service-route-upstream-mtls-auth/input.yaml b/file/testdata/kong2kic/custom_resources/yaml/9-service-route-upstream-mtls-auth/input.yaml new file mode 100644 index 000000000..f12055648 --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/9-service-route-upstream-mtls-auth/input.yaml @@ -0,0 +1,140 @@ +services: + - name: example-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 + routes: + - name: example-route + methods: + - GET + - POST + hosts: + - example.com + paths: + - /v1/example + protocols: + - http + - https + headers: + x-my-header: + - foo + - bar + x-another-header: + - bla + 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: mtls-auth + config: + ca_certificates: + - cce8c384-721f-4f58-85dd-50834e3e733a + skip_consumer_lookup: false + revocation_check_mode: SKIP +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 + host_header: example.com + client_certificate: + id: ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6 + use_srv_name: false +consumers: + - username: example-user + custom_id: "1234567890" + tags: + - internal + mtls_auth_credentials: + - id: cce8c384-721f-4f58-85dd-50834e3e733a + subject_name: example-user@example.com \ No newline at end of file diff --git a/file/testdata/kong2kic/custom_resources/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml b/file/testdata/kong2kic/custom_resources/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml new file mode 100644 index 000000000..01bebbf8e --- /dev/null +++ b/file/testdata/kong2kic/custom_resources/yaml/9-service-route-upstream-mtls-auth/output-expected.yaml @@ -0,0 +1,198 @@ +apiVersion: configuration.konghq.com/v1 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-service +proxy: + connect_timeout: 5000 + path: /v1 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 +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 +kind: KongIngress +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-route +route: + headers: + x-another-header: + - bla + x-my-header: + - foo + - bar + https_redirect_status_code: 302 + methods: + - GET + - POST + preserve_host: true + protocols: + - http + - https + regex_priority: 1 + snis: + - example.com + strip_path: false +--- +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 + creationTimestamp: null + name: mtls-auth +plugin: mtls-auth +status: {} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + konghq.com/override: example-route + konghq.com/plugins: mtls-auth + creationTimestamp: null + name: example-route +spec: + ingressClassName: kong + rules: + - host: example.com + http: + paths: + - backend: + service: + name: example-service + port: + number: 80 + path: /v1/example + pathType: ImplementationSpecific +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + konghq.com/override: example-service + creationTimestamp: null + name: example-service +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: example-service +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + 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: +- mtls-auth-example-user +custom_id: "1234567890" +kind: KongConsumer +metadata: + annotations: + kubernetes.io/ingress.class: kong + creationTimestamp: null + name: example-user +status: {} +username: example-user +--- diff --git a/file/types.go b/file/types.go index d70b60e2a..11cdfbf14 100644 --- a/file/types.go +++ b/file/types.go @@ -9,6 +9,11 @@ import ( "github.com/kong/deck/utils" "github.com/kong/go-kong/kong" + kicv1 "github.com/kong/kubernetes-ingress-controller/v2/pkg/apis/configuration/v1" + kicv1beta1 "github.com/kong/kubernetes-ingress-controller/v2/pkg/apis/configuration/v1beta1" + k8scorev1 "k8s.io/api/core/v1" + k8snetv1 "k8s.io/api/networking/v1" + "sigs.k8s.io/yaml" ) // Format is a file format for Kong's configuration. @@ -23,6 +28,11 @@ const ( JSON = "JSON" // YAML if YAML file format. YAML = "YAML" + // KIC YAML and JSON file format for ingress controller. + KICYAMLCrd = "KIC_YAML_CRD" + KICJSONCrd = "KIC_JSON_CRD" + KICYAMLAnnotation = "KIC_YAML_ANNOTATION" + KICJSONAnnotation = "KIC_JSON_ANNOTATION" ) const ( @@ -741,3 +751,198 @@ type Content struct { Licenses []FLicense `json:"licenses,omitempty" yaml:"licenses,omitempty"` } + +// KICContent represents a serialized Kong state for KIC. +// +k8s:deepcopy-gen=true +type KICContent struct { + KongIngresses []kicv1.KongIngress `json:"kongIngresses,omitempty" yaml:",omitempty"` + KongPlugins []kicv1.KongPlugin `json:"kongPlugins,omitempty" yaml:",omitempty"` + KongClusterPlugins []kicv1.KongClusterPlugin `json:"clusterPlugins,omitempty" yaml:",omitempty"` + Ingresses []k8snetv1.Ingress `json:"ingresses,omitempty" yaml:",omitempty"` + Services []k8scorev1.Service `json:"services,omitempty" yaml:",omitempty"` + Secrets []k8scorev1.Secret `json:"secrets,omitempty" yaml:",omitempty"` + KongConsumers []kicv1.KongConsumer `json:"consumers,omitempty" yaml:",omitempty"` + KongConsumerGroups []kicv1beta1.KongConsumerGroup `json:"consumerGroups,omitempty" yaml:",omitempty"` +} + +func (k KICContent) marshalKICContentToYaml() ([]byte, error) { + var kongIngresses []byte + var kongPlugins []byte + var kongClusterPlugins []byte + var ingresses []byte + var services []byte + var secrets []byte + var kongConsumers []byte + var kongConsumerGroups []byte + var err error + var output []byte + + // iterate over the slices of kongIngresses, kongPlugins, + // kongClusterPlugins, ingresses, services, secrets, kongConsumers + // and marshal each one in yaml format + // and append it to the output slice + // then return the output slice + for _, kongIngress := range k.KongIngresses { + kongIngresses, err = yaml.Marshal(kongIngress) + if err != nil { + return nil, err + } + output = append(output, kongIngresses...) + output = append(output, []byte("---\n")...) + } + + for _, kongPlugin := range k.KongPlugins { + kongPlugins, err = yaml.Marshal(kongPlugin) + if err != nil { + return nil, err + } + output = append(output, kongPlugins...) + output = append(output, []byte("---\n")...) + + } + + for _, kongClusterPlugin := range k.KongClusterPlugins { + kongClusterPlugins, err = yaml.Marshal(kongClusterPlugin) + if err != nil { + return nil, err + } + output = append(output, kongClusterPlugins...) + output = append(output, []byte("---\n")...) + + } + + for _, ingress := range k.Ingresses { + ingresses, err = yaml.Marshal(ingress) + if err != nil { + return nil, err + } + output = append(output, ingresses...) + output = append(output, []byte("---\n")...) + + } + + for _, service := range k.Services { + services, err = yaml.Marshal(service) + if err != nil { + return nil, err + } + output = append(output, services...) + output = append(output, []byte("---\n")...) + + } + + for _, secret := range k.Secrets { + secrets, err = yaml.Marshal(secret) + if err != nil { + return nil, err + } + output = append(output, secrets...) + output = append(output, []byte("---\n")...) + + } + + for _, kongConsumer := range k.KongConsumers { + kongConsumers, err = yaml.Marshal(kongConsumer) + if err != nil { + return nil, err + } + output = append(output, kongConsumers...) + output = append(output, []byte("---\n")...) + + } + + for _, kongConsumerGroup := range k.KongConsumerGroups { + kongConsumerGroups, err = yaml.Marshal(kongConsumerGroup) + if err != nil { + return nil, err + } + output = append(output, kongConsumerGroups...) + output = append(output, []byte("---\n")...) + } + + return output, nil +} + +func (k KICContent) marshalKICContentToJSON() ([]byte, error) { + var kongIngresses []byte + var kongPlugins []byte + var kongClusterPlugins []byte + var ingresses []byte + var services []byte + var secrets []byte + var kongConsumers []byte + var kongConsumerGroups []byte + var err error + var output []byte + + // iterate over the slices of kongIngresses, kongPlugins, + // kongClusterPlugins, ingresses, services, secrets, kongConsumers + // and marshal each one in json format + // and append it to the output slice + // then return the output slice + for _, kongIngress := range k.KongIngresses { + kongIngresses, err = json.MarshalIndent(kongIngress, "", " ") + if err != nil { + return nil, err + } + output = append(output, kongIngresses...) + } + + for _, kongPlugin := range k.KongPlugins { + kongPlugins, err = json.MarshalIndent(kongPlugin, "", " ") + if err != nil { + return nil, err + } + output = append(output, kongPlugins...) + } + + for _, kongClusterPlugin := range k.KongClusterPlugins { + kongClusterPlugins, err = json.MarshalIndent(kongClusterPlugin, "", " ") + if err != nil { + return nil, err + } + output = append(output, kongClusterPlugins...) + } + + for _, ingress := range k.Ingresses { + ingresses, err = json.MarshalIndent(ingress, "", " ") + if err != nil { + return nil, err + } + output = append(output, ingresses...) + } + + for _, service := range k.Services { + services, err = json.MarshalIndent(service, "", " ") + if err != nil { + return nil, err + } + output = append(output, services...) + } + + for _, secret := range k.Secrets { + secrets, err = json.MarshalIndent(secret, "", " ") + if err != nil { + return nil, err + } + output = append(output, secrets...) + } + + for _, kongConsumer := range k.KongConsumers { + kongConsumers, err = json.MarshalIndent(kongConsumer, "", " ") + if err != nil { + return nil, err + } + output = append(output, kongConsumers...) + } + + for _, kongConsumerGroup := range k.KongConsumerGroups { + kongConsumerGroups, err = json.MarshalIndent(kongConsumerGroup, "", " ") + if err != nil { + return nil, err + } + output = append(output, kongConsumerGroups...) + } + + return output, nil +} diff --git a/file/writer.go b/file/writer.go index d33632d0a..d39157953 100644 --- a/file/writer.go +++ b/file/writer.go @@ -801,6 +801,26 @@ func WriteContentToFile(content *Content, filename string, format Format) error if err != nil { return err } + case KICJSONCrd: + c, err = MarshalKongToKICJson(content, CUSTOMRESOURCE) + if err != nil { + return err + } + case KICYAMLCrd: + c, err = MarshalKongToKICYaml(content, CUSTOMRESOURCE) + if err != nil { + return err + } + case KICJSONAnnotation: + c, err = MarshalKongToKICJson(content, ANNOTATIONS) + if err != nil { + return err + } + case KICYAMLAnnotation: + c, err = MarshalKongToKICYaml(content, ANNOTATIONS) + if err != nil { + return err + } default: return fmt.Errorf("unknown file format: " + string(format)) } diff --git a/file/zz_generated.deepcopy.go b/file/zz_generated.deepcopy.go index 718589385..454c1d164 100644 --- a/file/zz_generated.deepcopy.go +++ b/file/zz_generated.deepcopy.go @@ -23,6 +23,10 @@ package file import ( kong "github.com/kong/go-kong/kong" + v1 "github.com/kong/kubernetes-ingress-controller/v2/pkg/apis/configuration/v1" + v1beta1 "github.com/kong/kubernetes-ingress-controller/v2/pkg/apis/configuration/v1beta1" + corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -749,6 +753,78 @@ func (in *Info) DeepCopy() *Info { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KICContent) DeepCopyInto(out *KICContent) { + *out = *in + if in.KongIngresses != nil { + in, out := &in.KongIngresses, &out.KongIngresses + *out = make([]v1.KongIngress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KongPlugins != nil { + in, out := &in.KongPlugins, &out.KongPlugins + *out = make([]v1.KongPlugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KongClusterPlugins != nil { + in, out := &in.KongClusterPlugins, &out.KongClusterPlugins + *out = make([]v1.KongClusterPlugin, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Ingresses != nil { + in, out := &in.Ingresses, &out.Ingresses + *out = make([]networkingv1.Ingress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Services != nil { + in, out := &in.Services, &out.Services + *out = make([]corev1.Service, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]corev1.Secret, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KongConsumers != nil { + in, out := &in.KongConsumers, &out.KongConsumers + *out = make([]v1.KongConsumer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KongConsumerGroups != nil { + in, out := &in.KongConsumerGroups, &out.KongConsumerGroups + *out = make([]v1beta1.KongConsumerGroup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KICContent. +func (in *KICContent) DeepCopy() *KICContent { + if in == nil { + return nil + } + out := new(KICContent) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Kong) DeepCopyInto(out *Kong) { *out = *in diff --git a/go.mod b/go.mod index 4bd4af61b..04a345840 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/imdario/mergo v0.3.16 github.com/kong/go-apiops v0.1.21 github.com/kong/go-kong v0.46.0 + github.com/kong/kubernetes-ingress-controller/v2 v2.11.1 github.com/mitchellh/go-homedir v1.1.0 github.com/shirou/gopsutil/v3 v3.23.7 github.com/spf13/cobra v1.7.0 @@ -28,50 +29,56 @@ require ( github.com/stretchr/testify v1.8.4 github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/sync v0.3.0 + k8s.io/api v0.28.1 + k8s.io/apiextensions-apiserver v0.28.0 + k8s.io/apimachinery v0.28.1 k8s.io/code-generator v0.28.2 sigs.k8s.io/yaml v1.3.0 ) require ( github.com/Kong/go-diff v1.2.2 // indirect - github.com/adrg/strutil v0.2.3 // indirect + github.com/adrg/strutil v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 // indirect - github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/emicklei/go-restful/v3 v3.10.1 // indirect + github.com/frankban/quicktest v1.14.5 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/getkin/kin-openapi v0.108.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/yaml v0.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kong/semver/v4 v4.0.1 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mozillazg/go-slugify v0.2.0 // indirect github.com/mozillazg/go-unidecode v0.2.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/nxadm/tail v1.4.8 // indirect + github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect @@ -79,25 +86,29 @@ require ( github.com/subosito/gotenv v1.4.2 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/pretty v1.2.1 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect - github.com/tklauser/numcpus v0.6.0 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.13.0 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect - golang.org/x/tools v0.8.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/text v0.12.0 // indirect + golang.org/x/tools v0.11.1 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/controller-runtime v0.15.1 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index 02a5e9fcb..933860d94 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ github.com/Kong/gojsondiff v1.3.2 h1:qIOVq2mUXt+NXy8Be5gRUee9TP3Ve0MbQSafg9bXKZE github.com/Kong/gojsondiff v1.3.2/go.mod h1:DiIxtU59q4alK7ecP+7k56C5UjgOviJ5gQVR2esEhYw= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/adrg/strutil v0.2.3 h1:WZVn3ItPBovFmP4wMHHVXUr8luRaHrbyIuLlHt32GZQ= -github.com/adrg/strutil v0.2.3/go.mod h1:+SNxbiH6t+O+5SZqIj5n/9i5yUjR+S3XXVrjEcN2mxg= +github.com/adrg/strutil v0.3.0 h1:bi/HB2zQbDihC8lxvATDTDzkT4bG7PATtVnDYp5rvq4= +github.com/adrg/strutil v0.3.0/go.mod h1:Jz0wzBVE6Uiy9wxo62YEqEY1Nwto3QlLl1Il5gkLKWU= github.com/alecthomas/jsonschema v0.0.0-20191017121752-4bb6e3fae4f2 h1:swGeCLPiUQ647AIRnFxnAHdzlg6IPpmU6QdkOPZINt8= github.com/alecthomas/jsonschema v0.0.0-20191017121752-4bb6e3fae4f2/go.mod h1:Juc2PrI3wtNfUwptSvAIeNx+HrETwHQs6nf+TkOJlOA= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -67,8 +67,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 h1:aRd8M7HJVZOqn/vhOzrGcQH0lNAMkqMn+pXUYkatmcA= github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= -github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -77,8 +77,10 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/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.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/getkin/kin-openapi v0.108.0 h1:EYf0GtsKa4hQNIlplGS+Au7NEfGQ1F7MoHD2kcVevPQ= @@ -96,14 +98,18 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre 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.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig v2.20.0+incompatible h1:4Xh3bDzO29j4TWNOI+24ubc0vbVFMg2PMnXKxK54/CA= +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/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -192,13 +198,13 @@ github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCS github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -215,11 +221,14 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kong/go-apiops v0.1.21 h1:ZUq+AR6JxAopDqdzbnJRem/r5PZ0n7tgC4RqW3RQtOw= github.com/kong/go-apiops v0.1.21/go.mod h1:kRdZwcEJ9S9aSyeJZ+AUXGnMEfpM5sg503Z0dEC3ARk= github.com/kong/go-kong v0.46.0 h1:9I6nlX63WymU5Sg+d13iZDVwpW5vXh8/v0zarU27dzI= github.com/kong/go-kong v0.46.0/go.mod h1:41Sot1N/n8UHBp+gE/6nOw3vuzoHbhMSyU/zOS7VzPE= +github.com/kong/kubernetes-ingress-controller/v2 v2.11.1 h1:ICadZZUXTEUE1O9ATVvB8ItNdHEQkF/SANv/CnLUbTw= +github.com/kong/kubernetes-ingress-controller/v2 v2.11.1/go.mod h1:BA6BvTy6b45Hw4nK5Oj6b29X8YjOPB8krhTgPr+hEQI= 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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -227,12 +236,14 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -242,8 +253,8 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -259,22 +270,27 @@ github.com/mozillazg/go-slugify v0.2.0 h1:SIhqDlnJWZH8OdiTmQgeXR28AOnypmAXPeOTcG github.com/mozillazg/go-slugify v0.2.0/go.mod h1:z7dPH74PZf2ZPFkyxx+zjPD8CNzRJNa1CGacv0gg8Ns= 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/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94= github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= +github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= +github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= @@ -311,7 +327,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= @@ -320,12 +335,14 @@ github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= -github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -357,7 +374,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -391,8 +408,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -427,8 +444,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -462,6 +479,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -491,8 +509,11 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -502,8 +523,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -545,6 +566,7 @@ golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -553,10 +575,11 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc= +golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -651,16 +674,17 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 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= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -683,6 +707,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= +k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= +k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= +k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= k8s.io/code-generator v0.28.2 h1:u47guga1rCWLnEnffF09p+cqj8B20oHOLoQ1lb1HGtQ= k8s.io/code-generator v0.28.2/go.mod h1:ueeSJZJ61NHBa0ccWLey6mwawum25vX61nRZ6WOzN9A= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= @@ -692,10 +722,15 @@ k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/controller-runtime v0.15.1 h1:9UvgKD4ZJGcj24vefUFgZFP3xej/3igL9BsOUTb/+4c= +sigs.k8s.io/controller-runtime v0.15.1/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=