Skip to content

Commit

Permalink
feat: add and test Kong IPv6 support
Browse files Browse the repository at this point in the history
  • Loading branch information
rainest committed Sep 12, 2023
1 parent f77d4d3 commit 9c91048
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 1 deletion.
10 changes: 10 additions & 0 deletions pkg/clusters/addons/kong/addon.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,16 @@ func (a *Addon) Deploy(ctx context.Context, cluster clusters.Cluster) error {
)
}

if cluster.IPFamily() == clusters.IPv6 {
a.deployArgs = append(a.deployArgs,
"--set", "proxy.address=[::]",
"--set", "admin.address=[::1]",
"--set", "status.address=[::]",
"--set", "cluster.address=[::]",
"--set", "ingressController.admissionWebhook.address=[::]",
)
}

// if the ingress controller is disabled flag it in the chart and don't install any CRDs
if a.ingressControllerDisabled {
a.deployArgs = append(a.deployArgs,
Expand Down
3 changes: 3 additions & 0 deletions pkg/clusters/addons/metallb/metallb.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ func deployMetallbForKindCluster(ctx context.Context, cluster clusters.Cluster,

func createIPAddressPool(ctx context.Context, cluster clusters.Cluster, dockerNetwork string) error {
// get an IP range for the docker container network to use for MetalLB
// this returns addresses based on the _Docker network_ the cluster runs on, not the cluster itself. this may,
// for example, return IPv4 addresses even for an IPv6-only cluster. although unsupported addresses will be listed
// in the IPAddressPool, speaker will not actually assign them if they are not compatible with the cluster network.
network, network6, err := docker.GetDockerContainerIPNetwork(docker.GetKindContainerID(cluster.Name()), dockerNetwork)
if err != nil {
return err
Expand Down
14 changes: 14 additions & 0 deletions pkg/clusters/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ import (
// Type indicates the type of Kubernetes cluster (e.g. Kind, GKE, e.t.c.)
type Type string

type IPFamily string

const (
// IPv4 indicates a Cluster that supports only IPv4 networking.
IPv4 IPFamily = "ipv4"
// IPv6 indicates a Cluster that supports only IPv6 networking.
IPv6 IPFamily = "ipv6"
// Dual indicates a Cluster that supports both IPv4 and IPv6 networking.
Dual IPFamily = "dual"
)

// Cluster objects represent a running Kubernetes cluster.
type Cluster interface {
// Name indicates the unique name of the running cluster.
Expand Down Expand Up @@ -51,6 +62,9 @@ type Cluster interface {
// of said directory and an error.
// It uses the provided meta string allow for diagnostics identification.
DumpDiagnostics(ctx context.Context, meta string) (string, error)

// IPFamily returns the cluster's IP networking capabilities.
IPFamily() IPFamily
}

type Builder interface {
Expand Down
2 changes: 2 additions & 0 deletions pkg/clusters/types/gke/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ func (b *Builder) Build(ctx context.Context) (clusters.Cluster, error) {
cfg: restCFG,
addons: make(clusters.Addons),
l: &sync.RWMutex{},
// we simply set this directly for GKE as we lack the ability to create other types of cluster
ipFamily: clusters.IPv4,
}

if err := utils.ClusterInitHooks(ctx, cluster); err != nil {
Expand Down
5 changes: 5 additions & 0 deletions pkg/clusters/types/gke/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Cluster struct {
cfg *rest.Config
addons clusters.Addons
l *sync.RWMutex
ipFamily clusters.IPFamily
}

// NewFromExistingWithEnv provides a new clusters.Cluster backed by an existing GKE cluster,
Expand Down Expand Up @@ -278,3 +279,7 @@ func (c *Cluster) DumpDiagnostics(ctx context.Context, meta string) (string, err

return outDir, err
}

func (c *Cluster) IPFamily() clusters.IPFamily {
return c.ipFamily
}
6 changes: 6 additions & 0 deletions pkg/clusters/types/kind/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,19 @@ func (b *Builder) Build(ctx context.Context) (clusters.Cluster, error) {
return nil, err
}

ipFamily := clusters.IPv4
if b.ipv6Only {
ipFamily = clusters.IPv6
}

cluster := &Cluster{
name: b.Name,
client: kc,
cfg: cfg,
addons: make(clusters.Addons),
deployArgs: deployArgs,
l: &sync.RWMutex{},
ipFamily: ipFamily,
}

if b.calicoCNI {
Expand Down
5 changes: 5 additions & 0 deletions pkg/clusters/types/kind/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Cluster struct {
addons clusters.Addons
deployArgs []string
l *sync.RWMutex
ipFamily clusters.IPFamily
}

// New provides a new clusters.Cluster backed by a Kind based Kubernetes Cluster.
Expand Down Expand Up @@ -158,3 +159,7 @@ func (c *Cluster) DumpDiagnostics(ctx context.Context, meta string) (string, err
err = clusters.DumpDiagnostics(ctx, c, meta, outDir)
return outDir, err
}

func (c *Cluster) IPFamily() clusters.IPFamily {
return c.ipFamily
}
30 changes: 29 additions & 1 deletion test/integration/ipv6_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
package integration

import (
"fmt"
"net"
"net/http"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/kong"
"github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/metallb"
"github.com/kong/kubernetes-testing-framework/pkg/environments"
)
Expand All @@ -19,7 +23,7 @@ func TestKindClusterWithIPv6(t *testing.T) {
t.Parallel()

t.Log("configuring the test environment with IPv6 only enabled")
builder := environments.NewBuilder().WithIPv6Only().WithAddons(metallb.New())
builder := environments.NewBuilder().WithIPv6Only().WithAddons(metallb.New(), kong.New())

t.Log("building the testing environment and Kubernetes cluster")
env, err := builder.Build(ctx)
Expand All @@ -36,4 +40,28 @@ func TestKindClusterWithIPv6(t *testing.T) {
require.Nil(t, parsed.To4())
}
}

require.Eventually(t, func() bool {
kongServices := env.Cluster().Client().CoreV1().Services(kong.DefaultNamespace)
service, err := kongServices.Get(ctx, kong.DefaultProxyServiceName, metav1.GetOptions{})
if err != nil {
return false
}

if len(service.Status.LoadBalancer.Ingress) == 0 {
return false
}

if net.ParseIP(service.Status.LoadBalancer.Ingress[0].IP).To4() != nil {
return false
}
kongURL := fmt.Sprintf("http://[%s]", service.Status.LoadBalancer.Ingress[0].IP)
resp, err := http.Get(kongURL)
// we don't care that the proxy has nothing to serve so long as we can talk to it and get a valid HTTP response
if err == nil && resp.StatusCode == http.StatusNotFound {
return true
}
return false

}, time.Minute*3, time.Second)
}

0 comments on commit 9c91048

Please sign in to comment.