Skip to content

Commit

Permalink
unittests for contour k8sd feature
Browse files Browse the repository at this point in the history
  • Loading branch information
maci3jka committed Sep 29, 2024
1 parent 1a7bafd commit d5d9439
Show file tree
Hide file tree
Showing 6 changed files with 640 additions and 45 deletions.
32 changes: 16 additions & 16 deletions src/k8s/pkg/k8sd/features/contour/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,29 @@ var (
ManifestPath: filepath.Join("charts", "ck-contour-common-1.28.2.tgz"),
}

// contourGatewayProvisionerEnvoyImageRepo represents the image to use for envoy in the gateway.
contourGatewayProvisionerEnvoyImageRepo = "ghcr.io/canonical/k8s-snap/envoyproxy/envoy"
// ContourGatewayProvisionerEnvoyImageRepo represents the image to use for envoy in the gateway.
ContourGatewayProvisionerEnvoyImageRepo = "ghcr.io/canonical/k8s-snap/envoyproxy/envoy"

// NOTE: The image version is v1.29.2 instead of 1.28.2
// to follow the upstream configuration for the contour gateway provisioner.
// contourGatewayProvisionerEnvoyImageTag is the tag to use for for envoy in the gateway.
contourGatewayProvisionerEnvoyImageTag = "v1.29.2"
// ContourGatewayProvisionerEnvoyImageTag is the tag to use for for envoy in the gateway.
ContourGatewayProvisionerEnvoyImageTag = "v1.29.2"

// contourIngressEnvoyImageRepo represents the image to use for the Contour Envoy proxy.
contourIngressEnvoyImageRepo = "ghcr.io/canonical/k8s-snap/bitnami/envoy"
// ContourIngressEnvoyImageRepo represents the image to use for the Contour Envoy proxy.
ContourIngressEnvoyImageRepo = "ghcr.io/canonical/k8s-snap/bitnami/envoy"

// contourIngressEnvoyImageTag is the tag to use for the Contour Envoy proxy image.
contourIngressEnvoyImageTag = "1.28.2-debian-12-r0"
// ContourIngressEnvoyImageTag is the tag to use for the Contour Envoy proxy image.
ContourIngressEnvoyImageTag = "1.28.2-debian-12-r0"

// contourIngressContourImageRepo represents the image to use for Contour.
contourIngressContourImageRepo = "ghcr.io/canonical/k8s-snap/bitnami/contour"
// ContourIngressContourImageRepo represents the image to use for Contour.
ContourIngressContourImageRepo = "ghcr.io/canonical/k8s-snap/bitnami/contour"

// contourIngressContourImageTag is the tag to use for the Contour image.
contourIngressContourImageTag = "1.28.2-debian-12-r4"
// ContourIngressContourImageTag is the tag to use for the Contour image.
ContourIngressContourImageTag = "1.28.2-debian-12-r4"

// contourGatewayProvisionerContourImageRepo represents the image to use for the Contour Gateway Provisioner.
contourGatewayProvisionerContourImageRepo = "ghcr.io/canonical/k8s-snap/projectcontour/contour"
// ContourGatewayProvisionerContourImageRepo represents the image to use for the Contour Gateway Provisioner.
ContourGatewayProvisionerContourImageRepo = "ghcr.io/canonical/k8s-snap/projectcontour/contour"

// contourGatewayProvisionerContourImageTag is the tag to use for the Contour Gateway Provisioner image.
contourGatewayProvisionerContourImageTag = "v1.28.2"
// ContourGatewayProvisionerContourImageTag is the tag to use for the Contour Gateway Provisioner image.
ContourGatewayProvisionerContourImageTag = "v1.28.2"
)
20 changes: 10 additions & 10 deletions src/k8s/pkg/k8sd/features/contour/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ func ApplyGateway(ctx context.Context, snap snap.Snap, gateway types.Gateway, ne
err = fmt.Errorf("failed to uninstall the contour gateway chart: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: contourGatewayProvisionerContourImageTag,
Version: ContourGatewayProvisionerContourImageTag,
Message: fmt.Sprintf(gatewayDeleteFailedMsgTmpl, err),
}, err
}
return types.FeatureStatus{
Enabled: false,
Version: contourGatewayProvisionerContourImageTag,
Version: ContourGatewayProvisionerContourImageTag,
Message: disabledMsg,
}, nil
}
Expand All @@ -48,7 +48,7 @@ func ApplyGateway(ctx context.Context, snap snap.Snap, gateway types.Gateway, ne
err = fmt.Errorf("failed to apply common contour CRDS: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: contourGatewayProvisionerContourImageTag,
Version: ContourGatewayProvisionerContourImageTag,
Message: fmt.Sprintf(gatewayDeployFailedMsgTmpl, err),
}, err
}
Expand All @@ -57,22 +57,22 @@ func ApplyGateway(ctx context.Context, snap snap.Snap, gateway types.Gateway, ne
err = fmt.Errorf("failed to wait for required contour common CRDs to be available: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: contourGatewayProvisionerContourImageTag,
Version: ContourGatewayProvisionerContourImageTag,
Message: fmt.Sprintf(gatewayDeployFailedMsgTmpl, err),
}, err
}

values := map[string]any{
"projectcontour": map[string]any{
"image": map[string]any{
"repository": contourGatewayProvisionerContourImageRepo,
"tag": contourGatewayProvisionerContourImageTag,
"repository": ContourGatewayProvisionerContourImageRepo,
"tag": ContourGatewayProvisionerContourImageTag,
},
},
"envoyproxy": map[string]any{
"image": map[string]any{
"repository": contourGatewayProvisionerEnvoyImageRepo,
"tag": contourGatewayProvisionerEnvoyImageTag,
"repository": ContourGatewayProvisionerEnvoyImageRepo,
"tag": ContourGatewayProvisionerEnvoyImageTag,
},
},
}
Expand All @@ -81,14 +81,14 @@ func ApplyGateway(ctx context.Context, snap snap.Snap, gateway types.Gateway, ne
err = fmt.Errorf("failed to install the contour gateway chart: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: contourGatewayProvisionerContourImageTag,
Version: ContourGatewayProvisionerContourImageTag,
Message: fmt.Sprintf(gatewayDeployFailedMsgTmpl, err),
}, err
}

return types.FeatureStatus{
Enabled: true,
Version: contourGatewayProvisionerContourImageTag,
Version: ContourGatewayProvisionerContourImageTag,
Message: enabledMsg,
}, nil
}
Expand Down
204 changes: 204 additions & 0 deletions src/k8s/pkg/k8sd/features/contour/gateway_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package contour_test

import (
"context"
"errors"
"testing"
"time"

helmmock "github.com/canonical/k8s/pkg/client/helm/mock"
"github.com/canonical/k8s/pkg/client/kubernetes"
"github.com/canonical/k8s/pkg/k8sd/features/contour"
"github.com/canonical/k8s/pkg/k8sd/types"
snapmock "github.com/canonical/k8s/pkg/snap/mock"

. "github.com/onsi/gomega"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakediscovery "k8s.io/client-go/discovery/fake"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"
)

func TestGatewayDisabled(t *testing.T) {
t.Run("HelmFailed", func(t *testing.T) {
g := NewWithT(t)

applyErr := errors.New("failed to apply")
helmM := &helmmock.Mock{
ApplyErr: applyErr,
}
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
},
}
network := types.Network{}
gateway := types.Gateway{
Enabled: ptr.To(false),
}

status, err := contour.ApplyGateway(context.Background(), snapM, gateway, network, nil)

g.Expect(err).To(HaveOccurred())
g.Expect(err.Error()).To(ContainSubstring(applyErr.Error()))
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(contour.ContourGatewayProvisionerContourImageTag))
g.Expect(status.Message).To(ContainSubstring("Failed to delete Contour Gateway"))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(1))

})

t.Run("Success", func(t *testing.T) {
g := NewWithT(t)

helmM := &helmmock.Mock{}
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
},
}
network := types.Network{}
gateway := types.Gateway{
Enabled: ptr.To(false),
}

status, err := contour.ApplyGateway(context.Background(), snapM, gateway, network, nil)

g.Expect(err).NotTo(HaveOccurred())
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(contour.ContourGatewayProvisionerContourImageTag))
g.Expect(status.Message).To(ContainSubstring("disabled"))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(1))

})
}

func TestGatewayEnabled(t *testing.T) {
t.Run("HelmFailed", func(t *testing.T) {
g := NewWithT(t)

applyErr := errors.New("failed to apply")
helmM := &helmmock.Mock{
ApplyErr: applyErr,
}
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
},
}
network := types.Network{}
gateway := types.Gateway{
Enabled: ptr.To(true),
}

status, err := contour.ApplyGateway(context.Background(), snapM, gateway, network, nil)

g.Expect(err).To(HaveOccurred())
g.Expect(err.Error()).To(ContainSubstring(applyErr.Error()))
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(contour.ContourGatewayProvisionerContourImageTag))
g.Expect(status.Message).To(ContainSubstring("Failed to deploy Contour Gateway"))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(1))
})

t.Run("Success", func(t *testing.T) {
g := NewWithT(t)

helmM := &helmmock.Mock{
ApplyChanged: true,
}
clientset := fake.NewSimpleClientset()
fakeDiscovery, ok := clientset.Discovery().(*fakediscovery.FakeDiscovery)
g.Expect(ok).To(BeTrue())
fakeDiscovery.Resources = []*v1.APIResourceList{
{
GroupVersion: "projectcontour.io/v1alpha1",
APIResources: []v1.APIResource{
{Name: "contourconfigurations"},
{Name: "contourdeployments"},
{Name: "extensionservices"},
},
},
{
GroupVersion: "projectcontour.io/v1",
APIResources: []v1.APIResource{
{Name: "tlscertificatedelegations"},
{Name: "httpproxies"},
},
}}
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
KubernetesClient: &kubernetes.Client{
Interface: clientset,
},
},
}
network := types.Network{}
gateway := types.Gateway{
Enabled: ptr.To(true),
}

status, err := contour.ApplyGateway(context.Background(), snapM, gateway, network, nil)

g.Expect(err).NotTo(HaveOccurred())
g.Expect(status.Enabled).To(BeTrue())
g.Expect(status.Version).To(Equal(contour.ContourGatewayProvisionerContourImageTag))
g.Expect(status.Message).To(ContainSubstring("enabled"))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(2))

values := helmM.ApplyCalledWith[1].Values
projectcontour := values["projectcontour"].(map[string]any)["image"].(map[string]any)
g.Expect(projectcontour["repository"]).To(Equal(contour.ContourGatewayProvisionerContourImageRepo))
g.Expect(projectcontour["tag"]).To(Equal(contour.ContourGatewayProvisionerContourImageTag))
envoy := values["envoyproxy"].(map[string]any)["image"].(map[string]any)
g.Expect(envoy["repository"]).To(Equal(contour.ContourGatewayProvisionerEnvoyImageRepo))
g.Expect(envoy["tag"]).To(Equal(contour.ContourGatewayProvisionerEnvoyImageTag))
})

t.Run("CrdDeploymentFailed", func(t *testing.T) {
g := NewWithT(t)

helmM := &helmmock.Mock{
ApplyChanged: true,
}
clientset := fake.NewSimpleClientset()
fakeDiscovery, ok := clientset.Discovery().(*fakediscovery.FakeDiscovery)
g.Expect(ok).To(BeTrue())
fakeDiscovery.Resources = []*v1.APIResourceList{
{
GroupVersion: "projectcontour.io/v1alpha1",
APIResources: []v1.APIResource{
{Name: "contourconfigurations"},
{Name: "contourdeployments"},
{Name: "extensionservices"},
},
},
{
GroupVersion: "projectcontour.io/v1",
APIResources: []v1.APIResource{},
}}
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
KubernetesClient: &kubernetes.Client{
Interface: clientset,
},
},
}
network := types.Network{}
gateway := types.Gateway{
Enabled: ptr.To(true),
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
defer cancel()
status, err := contour.ApplyGateway(ctx, snapM, gateway, network, nil)

g.Expect(err).To(HaveOccurred())
g.Expect(err.Error()).To(ContainSubstring("failed to wait for required contour common CRDs"))
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(contour.ContourGatewayProvisionerContourImageTag))
g.Expect(status.Message).To(ContainSubstring("Failed to deploy Contour Gateway"))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(1))
})
}
Loading

0 comments on commit d5d9439

Please sign in to comment.