Skip to content

Commit

Permalink
fix/feat: fix function ProxyUDPURL, introduce ProxyTCPURL and ProxyTL…
Browse files Browse the repository at this point in the history
…SURL (#1008)
  • Loading branch information
programmer04 authored Mar 22, 2024
1 parent e0f95e4 commit 4aafd24
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 49 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,22 @@

## Unreleased

## v0.46.0

### Breaking changes

- Fixed `ProxyUDPURL` function to return the correct URL (`<IP>:<PORT>`),
the type of returned value changed from `*url.URL` to `string`.
Renamed `ProxyURL` to `ProxyHTTPURL`.
[#1008](https://github.com/Kong/kubernetes-testing-framework/pull/1008)

### Added

- Added support for arbitrary Helm chart values to the Kuma plugin.
[#958](https://github.com/Kong/kubernetes-testing-framework/pull/958)
- Introduced new functions `ProxyTCPURL` and `ProxyTLSURL` that returns
the URL in the format `<IP>:<PORT>`. Introduced new function `ProxyHTTPSURL`.
[#1008](https://github.com/Kong/kubernetes-testing-framework/pull/1008)

## v0.45.0

Expand Down
111 changes: 67 additions & 44 deletions pkg/clusters/addons/kong/addon.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,46 +134,47 @@ func (a *Addon) Namespace() string {
// Kong Addon - Proxy Endpoint Methods
// -----------------------------------------------------------------------------

// ProxyURL provides a routable *url.URL for accessing the Kong proxy.
func (a *Addon) ProxyURL(ctx context.Context, cluster clusters.Cluster) (*url.URL, error) {
waitForObjects, ready, err := a.Ready(ctx, cluster)
// ProxyHTTPURL provides a routable *url.URL for accessing the Kong proxy.
func (a *Addon) ProxyHTTPURL(ctx context.Context, cluster clusters.Cluster) (*url.URL, error) {
urlStr, err := a.urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultProxyServiceName}, DefaultProxyHTTPPort)
if err != nil {
return nil, err
}
return url.Parse(urlStr)
}

if !ready {
return nil, fmt.Errorf("the addon is not ready on cluster %s: non-empty unresolved objects list: %+v", cluster.Name(), waitForObjects)
// ProxyHTTPSURL provides a routable *url.URL for accessing the Kong proxy.
func (a *Addon) ProxyHTTPSURL(ctx context.Context, cluster clusters.Cluster) (*url.URL, error) {
urlStr, err := a.urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultProxyServiceName}, DefaultProxyTLSServicePort)
if err != nil {
return nil, err
}

return urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultProxyServiceName}, DefaultProxyHTTPPort)
return url.Parse(urlStr)
}

// ProxyAdminURL provides a routable *url.URL for accessing the Kong Admin API.
func (a *Addon) ProxyAdminURL(ctx context.Context, cluster clusters.Cluster) (*url.URL, error) {
waitForObjects, ready, err := a.Ready(ctx, cluster)
urlStr, err := a.urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultAdminServiceName}, DefaultAdminServicePort)
if err != nil {
return nil, err
}

if !ready {
return nil, fmt.Errorf("the addon is not ready on cluster %s, see: %+v", cluster.Name(), waitForObjects)
}

return urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultAdminServiceName}, DefaultAdminServicePort)
return url.Parse(urlStr)
}

// ProxyUDPURL provides a routable *url.URL for accessing the default UDP service for the Kong Proxy.
func (a *Addon) ProxyUDPURL(ctx context.Context, cluster clusters.Cluster) (*url.URL, error) {
waitForObjects, ready, err := a.Ready(ctx, cluster)
if err != nil {
return nil, err
}
// ProxyUDPURL provides a routable address for accessing the default UDP service for the Kong Proxy.
func (a *Addon) ProxyUDPURL(ctx context.Context, cluster clusters.Cluster) (string, error) {
return a.urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultUDPServiceName}, DefaultUDPServicePort)
}

if !ready {
return nil, fmt.Errorf("the addon is not ready on cluster %s, see: %+v", cluster.Name(), waitForObjects)
}
// ProxyTCPURL provides a routable address for accessing the default TCP service for the Kong Proxy.
func (a *Addon) ProxyTCPURL(ctx context.Context, cluster clusters.Cluster) (string, error) {
// TCP port is exposed on the same service as the HTTP port.
return a.urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultProxyServiceName}, DefaultTCPServicePort)
}

return urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultUDPServiceName}, DefaultUDPServicePort)
// ProxyTLSURL provides a routable address for accessing the Kong proxy over TLS.
func (a *Addon) ProxyTLSURL(ctx context.Context, cluster clusters.Cluster) (string, error) {
return a.urlForService(ctx, cluster, types.NamespacedName{Namespace: a.namespace, Name: DefaultProxyServiceName}, DefaultTLSServicePort)
}

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -560,6 +561,48 @@ func (a *Addon) DumpDiagnostics(ctx context.Context, cluster clusters.Cluster) (
return diagnostics, nil
}

func (a *Addon) urlForService(ctx context.Context, cluster clusters.Cluster, nsn types.NamespacedName, port int) (string, error) {
waitForObjects, ready, err := a.Ready(ctx, cluster)
if err != nil {
return "", err
}

if !ready {
return "", fmt.Errorf("the addon is not ready on cluster %s, see: %+v", cluster.Name(), waitForObjects)
}

service, err := cluster.Client().CoreV1().Services(nsn.Namespace).Get(ctx, nsn.Name, metav1.GetOptions{})
if err != nil {
return "", err
}
var urlSchemePrefix string
switch port {
case DefaultAdminServicePort, DefaultProxyHTTPPort:
urlSchemePrefix = "http://"
case DefaultProxyTLSServicePort:
urlSchemePrefix = "https://"
default:
// To make URL parsable and without scheme, it is expected to start with "//".
urlSchemePrefix = ""
}

var ip string
switch service.Spec.Type {
case corev1.ServiceTypeLoadBalancer:
if len(service.Status.LoadBalancer.Ingress) == 1 {
ip = service.Status.LoadBalancer.Ingress[0].IP
}
default:
if service.Spec.ClusterIP != "" {
ip = service.Spec.ClusterIP
}
}
if ip == "" {
return "", fmt.Errorf("service %s has not yet been provisioned", service.Name)
}
return fmt.Sprintf("%s%s:%d", urlSchemePrefix, ip, port), nil
}

// -----------------------------------------------------------------------------
// Kong Addon - Private Secret Generation Config Options
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -624,26 +667,6 @@ func exposePortsDefault() []string {
}
}

func urlForService(ctx context.Context, cluster clusters.Cluster, nsn types.NamespacedName, port int) (*url.URL, error) {
service, err := cluster.Client().CoreV1().Services(nsn.Namespace).Get(ctx, nsn.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}

switch service.Spec.Type {
case corev1.ServiceTypeLoadBalancer:
if len(service.Status.LoadBalancer.Ingress) == 1 {
return url.Parse(fmt.Sprintf("http://%s:%d", service.Status.LoadBalancer.Ingress[0].IP, port))
}
default:
if service.Spec.ClusterIP != "" {
return url.Parse(fmt.Sprintf("http://%s:%d", service.Spec.ClusterIP, port))
}
}

return nil, fmt.Errorf("service %s has not yet been provisoned", service.Name)
}

// deployKongEnterpriseLicenseSecret deploys a Kubernetes secret containing the enterprise license data
// which the Kong proxy will use to validate an enable enterprise featuresets.
func deployKongEnterpriseLicenseSecret(ctx context.Context, cluster clusters.Cluster, namespace, name, licenseJSON string) error {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/gke_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func testGKECluster(t *testing.T, createSubnet bool) {
require.NoError(t, err)
kongAddonRaw, ok := kongAddon.(*kong.Addon)
require.True(t, ok)
proxyURL, err := kongAddonRaw.ProxyURL(ctx, env.Cluster())
proxyURL, err := kongAddonRaw.ProxyHTTPURL(ctx, env.Cluster())
require.NoError(t, err)
kongDeployment, err := env.Cluster().Client().AppsV1().Deployments(kongAddonRaw.Namespace()).Get(ctx, "ingress-controller-kong", metav1.GetOptions{})
require.NoError(t, err)
Expand Down
2 changes: 1 addition & 1 deletion test/integration/enterprise_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func deployAndTestKongEnterprise(t *testing.T, kongAddon *kongaddon.Addon, admin
require.NoError(t, <-env.WaitForReady(ctx))

t.Logf("verifying that the kong proxy service %s gets provisioned an IP address by metallb", kongaddon.DefaultProxyServiceName)
proxyURL, err := kongAddon.ProxyURL(ctx, env.Cluster())
proxyURL, err := kongAddon.ProxyHTTPURL(ctx, env.Cluster())
require.NoError(t, err)
require.NotNil(t, proxyURL)

Expand Down
2 changes: 1 addition & 1 deletion test/integration/kind_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestKindClusterBasics(t *testing.T) {
require.NoError(t, err)
kongAddonRaw, ok := kongAddon.(*kong.Addon)
require.True(t, ok)
proxyURL, err := kongAddonRaw.ProxyURL(ctx, env.Cluster())
proxyURL, err := kongAddonRaw.ProxyHTTPURL(ctx, env.Cluster())
require.NoError(t, err)

t.Log("verifying the kong proxy is returning its default 404 response")
Expand Down
2 changes: 1 addition & 1 deletion test/integration/metallb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestEnvironmentWithMetallb(t *testing.T) {
require.True(t, ready)

t.Logf("verifying that the kong proxy service %s gets provisioned an IP address by metallb", kongaddon.DefaultProxyServiceName)
proxyURL, err := kong.ProxyURL(ctx, env.Cluster())
proxyURL, err := kong.ProxyHTTPURL(ctx, env.Cluster())
require.NoError(t, err)
require.NotNil(t, proxyURL)

Expand Down
2 changes: 1 addition & 1 deletion test/integration/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestKongWithPostgresDBMode(t *testing.T) {
require.NoError(t, <-env.WaitForReady(ctx))

t.Logf("verifying that the kong proxy service %s gets provisioned an IP address by metallb", kongaddon.DefaultProxyServiceName)
proxyURL, err := kong.ProxyURL(ctx, env.Cluster())
proxyURL, err := kong.ProxyHTTPURL(ctx, env.Cluster())
require.NoError(t, err)
require.NotNil(t, proxyURL)

Expand Down

0 comments on commit 4aafd24

Please sign in to comment.