Skip to content

Commit

Permalink
Add unit tests for coredns (#684)
Browse files Browse the repository at this point in the history
* Add unit tests for coredns
KU-1515
  • Loading branch information
maci3jka authored Sep 20, 2024
1 parent 27c91c8 commit cfa7f99
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 13 deletions.
6 changes: 3 additions & 3 deletions src/k8s/pkg/k8sd/features/coredns/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

var (
// chartCoreDNS represents manifests to deploy CoreDNS.
chart = helm.InstallableChart{
Chart = helm.InstallableChart{
Name: "ck-dns",
Namespace: "kube-system",
ManifestPath: filepath.Join("charts", "coredns-1.29.0.tgz"),
Expand All @@ -17,6 +17,6 @@ var (
// imageRepo is the image to use for CoreDNS.
imageRepo = "ghcr.io/canonical/coredns"

// imageTag is the tag to use for the CoreDNS image.
imageTag = "1.11.1-ck4"
// ImageTag is the tag to use for the CoreDNS image.
ImageTag = "1.11.1-ck4"
)
18 changes: 9 additions & 9 deletions src/k8s/pkg/k8sd/features/coredns/coredns.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,25 @@ func ApplyDNS(ctx context.Context, snap snap.Snap, dns types.DNS, kubelet types.
m := snap.HelmClient()

if !dns.GetEnabled() {
if _, err := m.Apply(ctx, chart, helm.StateDeleted, nil); err != nil {
if _, err := m.Apply(ctx, Chart, helm.StateDeleted, nil); err != nil {
err = fmt.Errorf("failed to uninstall coredns: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: imageTag,
Version: ImageTag,
Message: fmt.Sprintf(deleteFailedMsgTmpl, err),
}, "", err
}
return types.FeatureStatus{
Enabled: false,
Version: imageTag,
Version: ImageTag,
Message: disabledMsg,
}, "", nil
}

values := map[string]any{
"image": map[string]any{
"repository": imageRepo,
"tag": imageTag,
"tag": ImageTag,
},
"service": map[string]any{
"name": "coredns",
Expand Down Expand Up @@ -82,11 +82,11 @@ func ApplyDNS(ctx context.Context, snap snap.Snap, dns types.DNS, kubelet types.
},
}

if _, err := m.Apply(ctx, chart, helm.StatePresent, values); err != nil {
if _, err := m.Apply(ctx, Chart, helm.StatePresent, values); err != nil {
err = fmt.Errorf("failed to apply coredns: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: imageTag,
Version: ImageTag,
Message: fmt.Sprintf(deployFailedMsgTmpl, err),
}, "", err
}
Expand All @@ -96,7 +96,7 @@ func ApplyDNS(ctx context.Context, snap snap.Snap, dns types.DNS, kubelet types.
err = fmt.Errorf("failed to create kubernetes client: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: imageTag,
Version: ImageTag,
Message: fmt.Sprintf(deployFailedMsgTmpl, err),
}, "", err
}
Expand All @@ -105,14 +105,14 @@ func ApplyDNS(ctx context.Context, snap snap.Snap, dns types.DNS, kubelet types.
err = fmt.Errorf("failed to retrieve the coredns service: %w", err)
return types.FeatureStatus{
Enabled: false,
Version: imageTag,
Version: ImageTag,
Message: fmt.Sprintf(deployFailedMsgTmpl, err),
}, "", err
}

return types.FeatureStatus{
Enabled: true,
Version: imageTag,
Version: ImageTag,
Message: fmt.Sprintf(enabledMsgTmpl, dnsIP),
}, dnsIP, err
}
198 changes: 198 additions & 0 deletions src/k8s/pkg/k8sd/features/coredns/coredns_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package coredns_test

import (
"context"
"errors"
"strings"
"testing"

. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/utils/ptr"

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

func TestDisabled(t *testing.T) {
t.Run("HelmApplyFails", 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,
},
}
dns := types.DNS{
Enabled: ptr.To(false),
}
kubelet := types.Kubelet{}

status, str, err := coredns.ApplyDNS(context.Background(), snapM, dns, kubelet, nil)

g.Expect(err).To(MatchError(ContainSubstring(applyErr.Error())))
g.Expect(str).To(BeEmpty())
g.Expect(status.Message).To(ContainSubstring(applyErr.Error()))
g.Expect(status.Message).To(ContainSubstring("failed to uninstall coredns"))
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(coredns.ImageTag))

callArgs := helmM.ApplyCalledWith[0]
g.Expect(callArgs.Chart).To(Equal(coredns.Chart))
g.Expect(callArgs.State).To(Equal(helm.StateDeleted))
g.Expect(callArgs.Values).To(BeNil())

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

helmM := &helmmock.Mock{}
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
},
}
dns := types.DNS{
Enabled: ptr.To(false),
}
kubelet := types.Kubelet{}

status, str, err := coredns.ApplyDNS(context.Background(), snapM, dns, kubelet, nil)

g.Expect(err).To(BeNil())
g.Expect(str).To(BeEmpty())
g.Expect(status.Message).To(Equal("disabled"))
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(coredns.ImageTag))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(1))

callArgs := helmM.ApplyCalledWith[0]
g.Expect(callArgs.Chart).To(Equal(coredns.Chart))
g.Expect(callArgs.State).To(Equal(helm.StateDeleted))
g.Expect(callArgs.Values).To(BeNil())
})
}

func TestEnabled(t *testing.T) {
t.Run("HelmApplyFails", 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,
},
}
dns := types.DNS{
Enabled: ptr.To(true),
}
kubelet := types.Kubelet{}

status, str, err := coredns.ApplyDNS(context.Background(), snapM, dns, kubelet, nil)

g.Expect(err).To(MatchError(ContainSubstring(applyErr.Error())))
g.Expect(str).To(BeEmpty())
g.Expect(status.Message).To(ContainSubstring(applyErr.Error()))
g.Expect(status.Message).To(ContainSubstring("failed to apply coredns"))
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(coredns.ImageTag))

callArgs := helmM.ApplyCalledWith[0]
g.Expect(callArgs.Chart).To(Equal(coredns.Chart))
g.Expect(callArgs.State).To(Equal(helm.StatePresent))
validateValues(g, callArgs.Values, dns, kubelet)
})
t.Run("HelmApplySuccessServiceFails", func(t *testing.T) {
g := NewWithT(t)

helmM := &helmmock.Mock{}
clientset := fake.NewSimpleClientset()
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
KubernetesClient: &kubernetes.Client{Interface: clientset},
},
}
dns := types.DNS{
Enabled: ptr.To(true),
}
kubelet := types.Kubelet{}

status, str, err := coredns.ApplyDNS(context.Background(), snapM, dns, kubelet, nil)

g.Expect(err).To(MatchError(ContainSubstring("services \"coredns\" not found")))
g.Expect(str).To(BeEmpty())
g.Expect(status.Message).To(ContainSubstring("failed to retrieve the coredns service"))
g.Expect(status.Enabled).To(BeFalse())
g.Expect(status.Version).To(Equal(coredns.ImageTag))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(1))

callArgs := helmM.ApplyCalledWith[0]
g.Expect(callArgs.Chart).To(Equal(coredns.Chart))
g.Expect(callArgs.State).To(Equal(helm.StatePresent))
validateValues(g, callArgs.Values, dns, kubelet)
})
t.Run("Success", func(t *testing.T) {
g := NewWithT(t)

helmM := &helmmock.Mock{}
clusterIp := "10.96.0.10"
corednsService := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "coredns",
Namespace: "kube-system",
},
Spec: corev1.ServiceSpec{
ClusterIP: clusterIp,
},
}
clientset := fake.NewSimpleClientset(corednsService)
snapM := &snapmock.Snap{
Mock: snapmock.Mock{
HelmClient: helmM,
KubernetesClient: &kubernetes.Client{Interface: clientset},
},
}
dns := types.DNS{
Enabled: ptr.To(true),
}
kubelet := types.Kubelet{}

status, str, err := coredns.ApplyDNS(context.Background(), snapM, dns, kubelet, nil)

g.Expect(err).To(BeNil())
g.Expect(str).To(Equal(clusterIp))
g.Expect(status.Message).To(ContainSubstring("enabled at " + clusterIp))
g.Expect(status.Enabled).To(BeTrue())
g.Expect(status.Version).To(Equal(coredns.ImageTag))
g.Expect(helmM.ApplyCalledWith).To(HaveLen(1))

callArgs := helmM.ApplyCalledWith[0]
g.Expect(callArgs.Chart).To(Equal(coredns.Chart))
g.Expect(callArgs.State).To(Equal(helm.StatePresent))
validateValues(g, callArgs.Values, dns, kubelet)
})
}

func validateValues(g Gomega, values map[string]any, dns types.DNS, kubelet types.Kubelet) {
service := values["service"].(map[string]any)
g.Expect(service["clusterIP"]).To(Equal(kubelet.GetClusterDNS()))

servers := values["servers"].([]map[string]any)
plugins := servers[0]["plugins"].([]map[string]any)
g.Expect(plugins[3]["parameters"]).To(ContainSubstring(kubelet.GetClusterDomain()))
g.Expect(plugins[5]["parameters"]).To(ContainSubstring(strings.Join(dns.GetUpstreamNameservers(), " ")))
}
2 changes: 1 addition & 1 deletion src/k8s/pkg/k8sd/features/coredns/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ import (

func init() {
images.Register(
fmt.Sprintf("%s:%s", imageRepo, imageTag),
fmt.Sprintf("%s:%s", imageRepo, ImageTag),
)
}

0 comments on commit cfa7f99

Please sign in to comment.