Skip to content

Commit

Permalink
Add tests for 'State()' in Application;
Browse files Browse the repository at this point in the history
  • Loading branch information
ycliuhw committed Aug 31, 2020
1 parent 7362e27 commit 5c9e892
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 24 deletions.
6 changes: 4 additions & 2 deletions caas/kubernetes/provider/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package application
import (
"context"
"fmt"
"sort"
"strings"

"github.com/juju/clock"
Expand Down Expand Up @@ -486,12 +487,12 @@ func (a *app) State() (caas.ApplicationState, error) {
}
state.DesiredReplicas = int(*d.Spec.Replicas)
case caas.DeploymentDaemon:
d := resources.NewDeployment(a.name, a.namespace, nil)
d := resources.NewDaemonSet(a.name, a.namespace, nil)
err := d.Get(context.Background(), a.client)
if err != nil {
return caas.ApplicationState{}, errors.Trace(err)
}
state.DesiredReplicas = int(d.Status.Replicas)
state.DesiredReplicas = int(d.Status.DesiredNumberScheduled)
default:
return caas.ApplicationState{}, errors.NotSupportedf("unknown deployment type")
}
Expand All @@ -512,6 +513,7 @@ func (a *app) State() (caas.ApplicationState, error) {
}
next = res.Continue
}
sort.Strings(state.Replicas)
return state, nil
}

Expand Down
205 changes: 183 additions & 22 deletions caas/kubernetes/provider/application/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ import (
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/cache"

// apicommoncharms "github.com/juju/juju/api/common/charms"
"github.com/juju/juju/caas"
"github.com/juju/juju/caas/kubernetes/provider/application"
"github.com/juju/juju/caas/kubernetes/provider/resources"
resourcesmocks "github.com/juju/juju/caas/kubernetes/provider/resources/mocks"
"github.com/juju/juju/core/paths"
// "github.com/juju/juju/caas/kubernetes/provider/storage"
k8swatcher "github.com/juju/juju/caas/kubernetes/provider/watcher"
k8swatchertest "github.com/juju/juju/caas/kubernetes/provider/watcher/test"
"github.com/juju/juju/core/paths"
"github.com/juju/juju/storage"
"github.com/juju/juju/testing"
)
Expand Down Expand Up @@ -696,9 +695,9 @@ func (s *applicationSuite) TestExistsDeployment(c *gc.C) {

app, _ := s.getApp(c, caas.DeploymentStateless, false)
// Deployment does not exists.
state, err := app.Exists()
result, err := app.Exists()
c.Assert(err, jc.ErrorIsNil)
c.Assert(state, gc.DeepEquals, caas.DeploymentState{})
c.Assert(result, gc.DeepEquals, caas.DeploymentState{})

// ensure a terminating Deployment.
dr := &appsv1.Deployment{
Expand All @@ -720,9 +719,9 @@ func (s *applicationSuite) TestExistsDeployment(c *gc.C) {
c.Assert(err, jc.ErrorIsNil)

// Deployment exists and is terminating.
state, err = app.Exists()
result, err = app.Exists()
c.Assert(err, jc.ErrorIsNil)
c.Assert(state, gc.DeepEquals, caas.DeploymentState{
c.Assert(result, gc.DeepEquals, caas.DeploymentState{
Exists: true, Terminating: true,
})
}
Expand All @@ -732,9 +731,9 @@ func (s *applicationSuite) TestExistsStatefulSet(c *gc.C) {

app, _ := s.getApp(c, caas.DeploymentStateful, false)
// Statefulset does not exists.
state, err := app.Exists()
result, err := app.Exists()
c.Assert(err, jc.ErrorIsNil)
c.Assert(state, gc.DeepEquals, caas.DeploymentState{})
c.Assert(result, gc.DeepEquals, caas.DeploymentState{})

// ensure a terminating Statefulset.
sr := &appsv1.StatefulSet{
Expand All @@ -756,9 +755,9 @@ func (s *applicationSuite) TestExistsStatefulSet(c *gc.C) {
c.Assert(err, jc.ErrorIsNil)

// Statefulset exists and is terminating.
state, err = app.Exists()
result, err = app.Exists()
c.Assert(err, jc.ErrorIsNil)
c.Assert(state, gc.DeepEquals, caas.DeploymentState{
c.Assert(result, gc.DeepEquals, caas.DeploymentState{
Exists: true, Terminating: true,
})

Expand All @@ -769,9 +768,9 @@ func (s *applicationSuite) TestExistsDaemonSet(c *gc.C) {

app, _ := s.getApp(c, caas.DeploymentDaemon, false)
// Daemonset does not exists.
state, err := app.Exists()
result, err := app.Exists()
c.Assert(err, jc.ErrorIsNil)
c.Assert(state, gc.DeepEquals, caas.DeploymentState{})
c.Assert(result, gc.DeepEquals, caas.DeploymentState{})

// ensure a terminating Daemonset.
dmr := &appsv1.DaemonSet{
Expand All @@ -793,9 +792,9 @@ func (s *applicationSuite) TestExistsDaemonSet(c *gc.C) {
c.Assert(err, jc.ErrorIsNil)

// Daemonset exists and is terminating.
state, err = app.Exists()
result, err = app.Exists()
c.Assert(err, jc.ErrorIsNil)
c.Assert(state, gc.DeepEquals, caas.DeploymentState{
c.Assert(result, gc.DeepEquals, caas.DeploymentState{
Exists: true, Terminating: true,
})

Expand Down Expand Up @@ -840,17 +839,179 @@ func (s *applicationSuite) TestDeleteDaemon(c *gc.C) {
c.Assert(app.Delete(), jc.ErrorIsNil)
}

func (s *applicationSuite) TestWatchNotsupported(c *gc.C) {
app, ctrl := s.getApp(c, caas.DeploymentType("notsupported"), true)
defer ctrl.Finish()

s.k8sWatcherFn = func(_ cache.SharedIndexInformer, _ string, _ jujuclock.Clock) (k8swatcher.KubernetesNotifyWatcher, error) {
w, _ := k8swatchertest.NewKubernetesTestWatcher()
return w, nil
}

_, err := app.Watch()
c.Assert(err, gc.ErrorMatches, `unknown deployment type not supported`)
}

func (s *applicationSuite) TestWatch(c *gc.C) {
app, ctrl := s.getApp(c, caas.DeploymentDaemon, true)
defer ctrl.Finish()

gomock.InOrder(
s.applier.EXPECT().Delete(resources.NewDaemonSet("gitlab", "test", nil)),
s.applier.EXPECT().Delete(resources.NewService("gitlab", "test", nil)),
s.applier.EXPECT().Delete(resources.NewSecret("gitlab-application-config", "test", nil)),
s.applier.EXPECT().Run(context.Background(), s.client, false).Return(nil),
)
c.Assert(app.Delete(), jc.ErrorIsNil)
s.k8sWatcherFn = func(_ cache.SharedIndexInformer, _ string, _ jujuclock.Clock) (k8swatcher.KubernetesNotifyWatcher, error) {
w, _ := k8swatchertest.NewKubernetesTestWatcher()
return w, nil
}

w, err := app.Watch()
c.Assert(err, jc.ErrorIsNil)

select {
case _, ok := <-w.Changes():
c.Assert(ok, jc.IsTrue)
case <-time.After(testing.LongWait):
c.Fatal("timed out waiting for event")
}
}

func (s *applicationSuite) TestWatchReplicas(c *gc.C) {
app, ctrl := s.getApp(c, caas.DeploymentDaemon, true)
defer ctrl.Finish()

s.k8sWatcherFn = func(_ cache.SharedIndexInformer, _ string, _ jujuclock.Clock) (k8swatcher.KubernetesNotifyWatcher, error) {
w, _ := k8swatchertest.NewKubernetesTestWatcher()
return w, nil
}

w, err := app.WatchReplicas()
c.Assert(err, jc.ErrorIsNil)

select {
case _, ok := <-w.Changes():
c.Assert(ok, jc.IsTrue)
case <-time.After(testing.LongWait):
c.Fatal("timed out waiting for event")
}
}

func (s *applicationSuite) TestStateNotsupported(c *gc.C) {
app, _ := s.getApp(c, caas.DeploymentType("notsupported"), false)
_, err := app.State()
c.Assert(err, gc.ErrorMatches, `unknown deployment type not supported`)
}

func (s *applicationSuite) assertState(c *gc.C, deploymentType caas.DeploymentType, createMainResource func() int) {
app, ctrl := s.getApp(c, deploymentType, false)
defer ctrl.Finish()

desiredReplicas := createMainResource()

pod1 := &corev1.Pod{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
Namespace: "test",
Labels: map[string]string{"juju-app": "gitlab"},
Annotations: map[string]string{"juju-version": "0.0.0"},
},
}
_, err := s.client.CoreV1().Pods("test").Create(context.TODO(),
pod1, metav1.CreateOptions{})
c.Assert(err, jc.ErrorIsNil)

pod2 := &corev1.Pod{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
Namespace: "test",
Labels: map[string]string{"juju-app": "gitlab"},
Annotations: map[string]string{"juju-version": "0.0.0"},
},
}
_, err = s.client.CoreV1().Pods("test").Create(context.TODO(),
pod2, metav1.CreateOptions{})
c.Assert(err, jc.ErrorIsNil)

appState, err := app.State()
c.Assert(err, jc.ErrorIsNil)
c.Assert(appState, gc.DeepEquals, caas.ApplicationState{
DesiredReplicas: desiredReplicas,
Replicas: []string{"pod1", "pod2"},
})
}
func (s *applicationSuite) TestStateStateful(c *gc.C) {
s.assertState(c, caas.DeploymentStateful, func() int {
desiredReplicas := 10

dmr := &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "gitlab",
Namespace: "test",
Labels: map[string]string{"juju-app": "gitlab"},
Annotations: map[string]string{"juju-version": "0.0.0"},
},
Spec: appsv1.StatefulSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"juju-app": "gitlab"},
},
Replicas: application.Int32Ptr(int32(desiredReplicas)),
},
}
_, err := s.client.AppsV1().StatefulSets("test").Create(context.TODO(),
dmr, metav1.CreateOptions{})
c.Assert(err, jc.ErrorIsNil)
return desiredReplicas
})
}

func (s *applicationSuite) TestStateStateless(c *gc.C) {
s.assertState(c, caas.DeploymentStateless, func() int {
desiredReplicas := 10

dmr := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "gitlab",
Namespace: "test",
Labels: map[string]string{"juju-app": "gitlab"},
Annotations: map[string]string{"juju-version": "0.0.0"},
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"juju-app": "gitlab"},
},
Replicas: application.Int32Ptr(int32(desiredReplicas)),
},
}
_, err := s.client.AppsV1().Deployments("test").Create(context.TODO(),
dmr, metav1.CreateOptions{})
c.Assert(err, jc.ErrorIsNil)
return desiredReplicas
})
}

func (s *applicationSuite) TestStateDaemon(c *gc.C) {
s.assertState(c, caas.DeploymentDaemon, func() int {
desiredReplicas := 10

dmr := &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Name: "gitlab",
Namespace: "test",
Labels: map[string]string{"juju-app": "gitlab"},
Annotations: map[string]string{"juju-version": "0.0.0"},
},
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"juju-app": "gitlab"},
},
},
Status: appsv1.DaemonSetStatus{
DesiredNumberScheduled: int32(desiredReplicas),
},
}
_, err := s.client.AppsV1().DaemonSets("test").Create(context.TODO(),
dmr, metav1.CreateOptions{})
c.Assert(err, jc.ErrorIsNil)
return desiredReplicas
})
}

type fakeCharm struct {
Expand Down

0 comments on commit 5c9e892

Please sign in to comment.