Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: restore Gateway API generation (issue #1427). #1431

Merged
merged 8 commits into from
Dec 13, 2024
4 changes: 2 additions & 2 deletions kong2kic/ca_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func populateKICCACertificate(content *file.Content, file *KICContent) {
continue
}
if caCert.CertDigest != nil {
secret.StringData["ca.digest"] = *caCert.CertDigest
secret.StringData[SecretCADigest] = *caCert.CertDigest
}

// add konghq.com/tags annotation if cacert.Tags is not nil
Expand All @@ -43,7 +43,7 @@ func populateKICCACertificate(content *file.Content, file *KICContent) {
tags = append(tags, *tag)
}
}
secret.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
secret.ObjectMeta.Annotations[KongHQTags] = strings.Join(tags, ",")
}

file.Secrets = append(file.Secrets, secret)
Expand Down
2 changes: 1 addition & 1 deletion kong2kic/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func populateKICCertificates(content *file.Content, file *KICContent) {
tags = append(tags, *tag)
}
}
secret.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
secret.ObjectMeta.Annotations[KongHQTags] = strings.Join(tags, ",")
}

file.Secrets = append(file.Secrets, secret)
Expand Down
4 changes: 2 additions & 2 deletions kong2kic/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ func populateKICConsumers(content *file.Content, file *KICContent) error {
username := *consumer.Username
kongConsumer := configurationv1.KongConsumer{
TypeMeta: metav1.TypeMeta{
APIVersion: KICAPIVersion,
Kind: "KongConsumer",
APIVersion: ConfigurationKongHQv1,
Kind: KongConsumerKind,
},
ObjectMeta: metav1.ObjectMeta{
Name: calculateSlug(username),
Expand Down
4 changes: 2 additions & 2 deletions kong2kic/consumer_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ func createCredentialSecret(consumerUsername, credentialType string, dataFields
stringData := make(map[string]string)
labels := map[string]string{}
if targetKICVersionAPI == KICV3GATEWAY || targetKICVersionAPI == KICV3INGRESS {
labels["konghq.com/credential"] = credentialType
labels[KongHQCredential] = credentialType
} else {
stringData["kongCredType"] = credentialType
stringData[KongCredType] = credentialType
}

// Add the data fields to stringData
Expand Down
8 changes: 4 additions & 4 deletions kong2kic/consumer_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func createConsumerGroupKongPlugin(
pluginName := *plugin.Name
kongPlugin := &configurationv1.KongPlugin{
TypeMeta: metav1.TypeMeta{
APIVersion: "configuration.konghq.com/v1",
Kind: "KongPlugin",
APIVersion: ConfigurationKongHQv1,
Kind: KongPluginKind,
},
ObjectMeta: metav1.ObjectMeta{
Name: calculateSlug(ownerName + "-" + pluginName),
Expand Down Expand Up @@ -55,8 +55,8 @@ func populateKICConsumerGroups(content *file.Content, kicContent *KICContent) er

kongConsumerGroup := configurationv1beta1.KongConsumerGroup{
TypeMeta: metav1.TypeMeta{
APIVersion: "configuration.konghq.com/v1beta1",
Kind: "KongConsumerGroup",
APIVersion: ConfigurationKongHQv1beta1,
Kind: KongConsumerGroupKind,
},
ObjectMeta: metav1.ObjectMeta{
Name: calculateSlug(groupName),
Expand Down
6 changes: 3 additions & 3 deletions kong2kic/global_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ func populateKICKongClusterPlugins(content *file.Content, file *KICContent) erro
continue
}
var kongClusterPlugin configurationv1.KongClusterPlugin
kongClusterPlugin.APIVersion = KICAPIVersion
kongClusterPlugin.Kind = "KongClusterPlugin"
kongClusterPlugin.APIVersion = ConfigurationKongHQv1
kongClusterPlugin.Kind = KongClusterPluginKind
kongClusterPlugin.ObjectMeta.Annotations = map[string]string{IngressClass: ClassName}
if plugin.Name != nil {
kongClusterPlugin.PluginName = *plugin.Name
Expand Down Expand Up @@ -65,7 +65,7 @@ func populateKICKongClusterPlugins(content *file.Content, file *KICContent) erro
tags = append(tags, *tag)
}
}
kongClusterPlugin.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
kongClusterPlugin.ObjectMeta.Annotations[KongHQTags] = strings.Join(tags, ",")
}

// transform the plugin config from map[string]interface{} to apiextensionsv1.JSON
Expand Down
16 changes: 0 additions & 16 deletions kong2kic/kong2kic.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,6 @@ import (
"github.com/kong/go-database-reconciler/pkg/file"
)

const (
KICV3GATEWAY = "KICV3_GATEWAY"
KICV3INGRESS = "KICV3_INGRESS"
KICV2GATEWAY = "KICV2_GATEWAY"
KICV2INGRESS = "KICV2_INGRESS"
KICAPIVersion = "configuration.konghq.com/v1"
KICAPIVersionV1Beta1 = "configuration.konghq.com/v1beta1"
GatewayAPIVersionV1Beta1 = "gateway.networking.k8s.io/v1beta1"
GatewayAPIVersionV1 = "gateway.networking.k8s.io/v1"
KongPluginKind = "KongPlugin"
SecretKind = "Secret"
IngressKind = "KongIngress"
UpstreamPolicyKind = "KongUpstreamPolicy"
IngressClass = "kubernetes.io/ingress.class"
)

// ClassName is set by the CLI flag --class-name
var ClassName = "kong"

Expand Down
88 changes: 51 additions & 37 deletions kong2kic/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@
protocols = append(protocols, *protocol)
}
}
annotations["konghq.com/protocols"] = strings.Join(protocols, ",")
annotations[KongHQProtocols] = strings.Join(protocols, ",")
}
if route.StripPath != nil {
annotations["konghq.com/strip-path"] = strconv.FormatBool(*route.StripPath)
annotations[KongHQStripPath] = strconv.FormatBool(*route.StripPath)
}
if route.PreserveHost != nil {
annotations["konghq.com/preserve-host"] = strconv.FormatBool(*route.PreserveHost)
annotations[KongHQPreserveHost] = strconv.FormatBool(*route.PreserveHost)
}
if route.RegexPriority != nil {
annotations["konghq.com/regex-priority"] = strconv.Itoa(*route.RegexPriority)
annotations[KongHQRegexPriority] = strconv.Itoa(*route.RegexPriority)
}
if route.HTTPSRedirectStatusCode != nil {
annotations["konghq.com/https-redirect-status-code"] = strconv.Itoa(*route.HTTPSRedirectStatusCode)
annotations[KongHQHTTPSRedirectStatusCode] = strconv.Itoa(*route.HTTPSRedirectStatusCode)
}
if route.Headers != nil {
for key, value := range route.Headers {
annotations["konghq.com/headers."+key] = strings.Join(value, ",")
annotations[KongHQHeaders+"."+key] = strings.Join(value, ",")
}
}
if route.PathHandling != nil {
annotations["konghq.com/path-handling"] = *route.PathHandling
annotations[KongHQPathHandling] = *route.PathHandling
}
if route.SNIs != nil {
var snis []string
Expand All @@ -55,13 +55,13 @@
snis = append(snis, *sni)
}
}
annotations["konghq.com/snis"] = strings.Join(snis, ",")
annotations[KongHQSNIs] = strings.Join(snis, ",")
}
if route.RequestBuffering != nil {
annotations["konghq.com/request-buffering"] = strconv.FormatBool(*route.RequestBuffering)
annotations[KongHQRequestBuffering] = strconv.FormatBool(*route.RequestBuffering)
}
if route.ResponseBuffering != nil {
annotations["konghq.com/response-buffering"] = strconv.FormatBool(*route.ResponseBuffering)
annotations[KongHQResponseBuffering] = strconv.FormatBool(*route.ResponseBuffering)
}
if route.Methods != nil {
var methods []string
Expand All @@ -70,7 +70,8 @@
methods = append(methods, *method)
}
}
annotations["konghq.com/methods"] = strings.Join(methods, ",")

annotations[KongHQMethods] = strings.Join(methods, ",")
}
if route.Tags != nil {
var tags []string
Expand All @@ -79,7 +80,7 @@
tags = append(tags, *tag)
}
}
annotations["konghq.com/tags"] = strings.Join(tags, ",")
annotations[KongHQTags] = strings.Join(tags, ",")
}
}

Expand All @@ -106,7 +107,7 @@
if *servicePort > 65535 || *servicePort < 0 {
log.Fatalf("Port %d is not within the valid range. Please provide a port between 0 and 65535.\n", *servicePort)
}
backend.Service.Port.Number = int32(*servicePort)
backend.Service.Port.Number = int32(*servicePort) //nolint:gosec

Check failure on line 110 in kong2kic/route.go

View workflow job for this annotation

GitHub Actions / lint

directive `//nolint:gosec` is unused for linter "gosec" (nolintlint)
}
paths = append(paths, k8snetv1.HTTPIngressPath{
Path: sCopy,
Expand Down Expand Up @@ -134,8 +135,8 @@

k8sIngress := k8snetv1.Ingress{
TypeMeta: metav1.TypeMeta{
APIVersion: "networking.k8s.io/v1",
Kind: "Ingress",
APIVersion: IngressAPIVersion,
Kind: IngressKind,
},
ObjectMeta: metav1.ObjectMeta{
Name: calculateSlug(serviceName + "-" + routeName),
Expand Down Expand Up @@ -197,7 +198,7 @@
pluginName := *plugin.Name
kongPlugin := configurationv1.KongPlugin{
TypeMeta: metav1.TypeMeta{
APIVersion: KICAPIVersion,
APIVersion: ConfigurationKongHQv1,
Kind: KongPluginKind,
},
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -236,7 +237,7 @@
tags = append(tags, *tag)
}
}
kongPlugin.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
kongPlugin.ObjectMeta.Annotations[KongHQTags] = strings.Join(tags, ",")
}

configJSON, err := json.Marshal(plugin.Config)
Expand All @@ -248,11 +249,11 @@
}

// Add plugin reference to ingress annotations
pluginsAnnotation := ingress.ObjectMeta.Annotations["konghq.com/plugins"]
pluginsAnnotation := ingress.ObjectMeta.Annotations[KongHQPlugins]
if pluginsAnnotation == "" {
ingress.ObjectMeta.Annotations["konghq.com/plugins"] = kongPlugin.ObjectMeta.Name
ingress.ObjectMeta.Annotations[KongHQPlugins] = kongPlugin.ObjectMeta.Name
} else {
ingress.ObjectMeta.Annotations["konghq.com/plugins"] = pluginsAnnotation + "," + kongPlugin.ObjectMeta.Name
ingress.ObjectMeta.Annotations[KongHQPlugins] = pluginsAnnotation + "," + kongPlugin.ObjectMeta.Name
}

kicContent.KongPlugins = append(kicContent.KongPlugins, kongPlugin)
Expand Down Expand Up @@ -312,7 +313,8 @@

func createHTTPRoute(service file.FService, route *file.FRoute) (k8sgwapiv1.HTTPRoute, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do a lot of dereferencing for service and route here. Can we do a nil check beforehand to avoid potential panics?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provided comments on the concrete potential nil-checking.

var httpRoute k8sgwapiv1.HTTPRoute
httpRoute.Kind = "HTTPRoute"

httpRoute.Kind = HTTPRouteKind
if targetKICVersionAPI == KICV3GATEWAY {
httpRoute.APIVersion = GatewayAPIVersionV1
} else {
Expand All @@ -338,20 +340,20 @@

func addAnnotations(httpRoute *k8sgwapiv1.HTTPRoute, route *file.FRoute) {
if route.PreserveHost != nil {
httpRoute.ObjectMeta.Annotations["konghq.com/preserve-host"] = strconv.FormatBool(*route.PreserveHost)
httpRoute.ObjectMeta.Annotations[KongHQPreserveHost] = strconv.FormatBool(*route.PreserveHost)
}
if route.StripPath != nil {
httpRoute.ObjectMeta.Annotations["konghq.com/strip-path"] = strconv.FormatBool(*route.StripPath)
httpRoute.ObjectMeta.Annotations[KongHQStripPath] = strconv.FormatBool(*route.StripPath)
}
if route.HTTPSRedirectStatusCode != nil {
value := strconv.Itoa(*route.HTTPSRedirectStatusCode)
httpRoute.ObjectMeta.Annotations["konghq.com/https-redirect-status-code"] = value
httpRoute.ObjectMeta.Annotations[KongHQHTTPSRedirectStatusCode] = value
}
if route.RegexPriority != nil {
httpRoute.ObjectMeta.Annotations["konghq.com/regex-priority"] = strconv.Itoa(*route.RegexPriority)
httpRoute.ObjectMeta.Annotations[KongHQRegexPriority] = strconv.Itoa(*route.RegexPriority)
}
if route.PathHandling != nil {
httpRoute.ObjectMeta.Annotations["konghq.com/path-handling"] = *route.PathHandling
httpRoute.ObjectMeta.Annotations[KongHQPathHandling] = *route.PathHandling
}
if route.Tags != nil {
var tags []string
Expand All @@ -360,24 +362,25 @@
tags = append(tags, *tag)
}
}
httpRoute.ObjectMeta.Annotations["konghq.com/tags"] = strings.Join(tags, ",")
httpRoute.ObjectMeta.Annotations[KongHQTags] = strings.Join(tags, ",")
}
if route.SNIs != nil {
var snis string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance wise, it would be better to use a string builder.
I will leave the choice to you. If this piece of code isn't accessed much, we can leave it as is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, refactored as a string builder.

var sb strings.Builder
for _, sni := range route.SNIs {
if snis == "" {
snis = *sni
} else {
snis = snis + "," + *sni
if sb.Len() > 0 {
sb.WriteString(",")
}
sb.WriteString(*sni)
}
httpRoute.ObjectMeta.Annotations["konghq.com/snis"] = snis
snis = sb.String()
httpRoute.ObjectMeta.Annotations[KongHQSNIs] = snis
}
if route.RequestBuffering != nil {
httpRoute.ObjectMeta.Annotations["konghq.com/request-buffering"] = strconv.FormatBool(*route.RequestBuffering)
httpRoute.ObjectMeta.Annotations[KongHQRequestBuffering] = strconv.FormatBool(*route.RequestBuffering)
}
if route.ResponseBuffering != nil {
httpRoute.ObjectMeta.Annotations["konghq.com/response-buffering"] = strconv.FormatBool(*route.ResponseBuffering)
httpRoute.ObjectMeta.Annotations[KongHQResponseBuffering] = strconv.FormatBool(*route.ResponseBuffering)
}
}

Expand All @@ -395,7 +398,11 @@
})
}

// Adds backend references to the given HTTPRoute based on the provided service and route.
// It constructs BackendRef, HTTPHeaderMatch, and HTTPPathMatch objects and appends them to the HTTPRoute's rules.
// The function handles different matching types for headers and paths, and supports multiple methods for each route.
func addBackendRefs(httpRoute *k8sgwapiv1.HTTPRoute, service file.FService, route *file.FRoute) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please add some comments in this function to ensure that future contributors can understand what needs to be done and why?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments added. Let me know if it is clear.

// make this HTTPRoute point to the service
backendRef := k8sgwapiv1.BackendRef{
BackendObjectReference: k8sgwapiv1.BackendObjectReference{
Name: k8sgwapiv1.ObjectName(*service.Name),
Expand All @@ -406,18 +413,21 @@
backendRef.Port = &portNumber
}

// add header match conditions to the HTTPRoute
var httpHeaderMatch []k8sgwapiv1.HTTPHeaderMatch
headerMatchExact := k8sgwapiv1.HeaderMatchExact
headerMatchRegex := k8sgwapiv1.HeaderMatchRegularExpression
if route.Headers != nil {
for key, values := range route.Headers {
if len(values) == 1 && strings.HasPrefix(values[0], "~*") {
// it's a regular expression header match condition
httpHeaderMatch = append(httpHeaderMatch, k8sgwapiv1.HTTPHeaderMatch{
Name: k8sgwapiv1.HTTPHeaderName(key),
Value: values[0][2:],
Type: &headerMatchRegex,
})
} else {
// it's an exact header match condition
var value string
if len(values) > 1 {
value = strings.Join(values, ",")
Expand All @@ -435,21 +445,25 @@
}

if route.Paths != nil {
// evaluate each path and method combination and add them to the HTTPRoute
for _, path := range route.Paths {
var httpPathMatch k8sgwapiv1.HTTPPathMatch
pathMatchRegex := k8sgwapiv1.PathMatchRegularExpression
pathMatchPrefix := k8sgwapiv1.PathMatchPathPrefix

if strings.HasPrefix(*path, "~") {
// add regex path match condition
httpPathMatch.Type = &pathMatchRegex
regexPath := (*path)[1:]
httpPathMatch.Value = &regexPath
} else {
// add regular path match condition
httpPathMatch.Type = &pathMatchPrefix
httpPathMatch.Value = path
}

if route.Methods == nil {
// this route has specific http methods to match
httpRoute.Spec.Rules = append(httpRoute.Spec.Rules, k8sgwapiv1.HTTPRouteRule{
Matches: []k8sgwapiv1.HTTPRouteMatch{
{
Expand Down Expand Up @@ -507,8 +521,8 @@
service file.FService, route *file.FRoute, httpRoute k8sgwapiv1.HTTPRoute, kicContent *KICContent,
) error {
for _, plugin := range route.Plugins {
var kongPlugin kicv1.KongPlugin
kongPlugin.APIVersion = KICAPIVersion
var kongPlugin configurationv1.KongPlugin
kongPlugin.APIVersion = ConfigurationKongHQv1
kongPlugin.Kind = KongPluginKind
if plugin.Name != nil && route.Name != nil && service.Name != nil {
kongPlugin.ObjectMeta.Name = calculateSlug(*service.Name + "-" + *route.Name + "-" + *plugin.Name)
Expand All @@ -534,7 +548,7 @@
ExtensionRef: &k8sgwapiv1.LocalObjectReference{
Name: k8sgwapiv1.ObjectName(kongPlugin.ObjectMeta.Name),
Kind: KongPluginKind,
Group: "configuration.konghq.com",
Group: ConfigurationKongHQ,
},
Type: k8sgwapiv1.HTTPRouteFilterExtensionRef,
})
Expand Down
Loading
Loading