Add unit tests for rollout status command

This commit makes adjustments in rollout status command to make it
unit testable. In addition to that, unit tests for rollout status
command is added.
This commit is contained in:
Arda Güçlü 2022-06-13 15:10:26 +03:00
parent 26002596b2
commit f21e5983a9
2 changed files with 245 additions and 6 deletions

View File

@ -134,12 +134,7 @@ func (o *RolloutStatusOptions) Complete(f cmdutil.Factory, args []string) error
o.BuilderArgs = args
o.StatusViewerFn = polymorphichelpers.StatusViewerFn
clientConfig, err := f.ToRESTConfig()
if err != nil {
return err
}
o.DynamicClient, err = dynamic.NewForConfig(clientConfig)
o.DynamicClient, err = f.DynamicClient()
if err != nil {
return err
}

View File

@ -0,0 +1,244 @@
package rollout
import (
"bytes"
"io/ioutil"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/rest/fake"
cgtesting "k8s.io/client-go/testing"
"k8s.io/kubectl/pkg/scheme"
"net/http"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions"
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
)
var rolloutStatusGroupVersionEncoder = schema.GroupVersion{Group: "apps", Version: "v1"}
func TestRolloutStatus(t *testing.T) {
deploymentName := "deployment/nginx-deployment"
ns := scheme.Codecs.WithoutConversion()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON)
encoder := ns.EncoderForVersion(info.Serializer, rolloutStatusGroupVersionEncoder)
tf.Client = &fake.RESTClient{
GroupVersion: rolloutStatusGroupVersionEncoder,
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
dep := &appsv1.Deployment{}
dep.Name = deploymentName
body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, dep))))
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
}),
}
tf.FakeDynamicClient.WatchReactionChain = nil
tf.FakeDynamicClient.AddWatchReactor("*", func(action cgtesting.Action) (handled bool, ret watch.Interface, err error) {
fw := watch.NewFake()
dep := &appsv1.Deployment{}
dep.Name = deploymentName
dep.Status = appsv1.DeploymentStatus{
Replicas: 1,
UpdatedReplicas: 1,
ReadyReplicas: 1,
AvailableReplicas: 1,
UnavailableReplicas: 0,
Conditions: []appsv1.DeploymentCondition{{
Type: appsv1.DeploymentAvailable,
}},
}
c, err := runtime.DefaultUnstructuredConverter.ToUnstructured(dep.DeepCopyObject())
if err != nil {
t.Errorf("unexpected err %s", err)
}
u := &unstructured.Unstructured{}
u.SetUnstructuredContent(c)
go fw.Add(u)
return true, fw, nil
})
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdRolloutStatus(tf, streams)
cmd.Run(cmd, []string{deploymentName})
expectedMsg := "deployment \"deployment/nginx-deployment\" successfully rolled out\n"
if buf.String() != expectedMsg {
t.Errorf("expected output: %s, but got: %s", expectedMsg, buf.String())
}
}
func TestRolloutStatusWithSelector(t *testing.T) {
deploymentName := "deployment"
ns := scheme.Codecs.WithoutConversion()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON)
encoder := ns.EncoderForVersion(info.Serializer, rolloutStatusGroupVersionEncoder)
tf.Client = &fake.RESTClient{
GroupVersion: rolloutStatusGroupVersionEncoder,
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
dep := &appsv1.Deployment{}
dep.Name = deploymentName
dep.Labels = make(map[string]string)
dep.Labels["app"] = "api"
body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, dep))))
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
}),
}
tf.FakeDynamicClient.WatchReactionChain = nil
tf.FakeDynamicClient.AddWatchReactor("*", func(action cgtesting.Action) (handled bool, ret watch.Interface, err error) {
fw := watch.NewFake()
dep := &appsv1.Deployment{}
dep.Name = deploymentName
dep.Status = appsv1.DeploymentStatus{
Replicas: 1,
UpdatedReplicas: 1,
ReadyReplicas: 1,
AvailableReplicas: 1,
UnavailableReplicas: 0,
Conditions: []appsv1.DeploymentCondition{{
Type: appsv1.DeploymentAvailable,
}},
}
dep.Labels = make(map[string]string)
dep.Labels["app"] = "api"
c, err := runtime.DefaultUnstructuredConverter.ToUnstructured(dep.DeepCopyObject())
if err != nil {
t.Errorf("unexpected err %s", err)
}
u := &unstructured.Unstructured{}
u.SetUnstructuredContent(c)
go fw.Add(u)
return true, fw, nil
})
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdRolloutStatus(tf, streams)
cmd.Flags().Set("selector", "app=api")
cmd.Run(cmd, []string{deploymentName})
expectedMsg := "deployment \"deployment\" successfully rolled out\n"
if buf.String() != expectedMsg {
t.Errorf("expected output: %s, but got: %s", expectedMsg, buf.String())
}
}
func TestRolloutStatusWatchDisabled(t *testing.T) {
deploymentName := "deployment/nginx-deployment"
ns := scheme.Codecs.WithoutConversion()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON)
encoder := ns.EncoderForVersion(info.Serializer, rolloutStatusGroupVersionEncoder)
tf.Client = &fake.RESTClient{
GroupVersion: rolloutStatusGroupVersionEncoder,
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
dep := &appsv1.Deployment{}
dep.Name = deploymentName
body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, dep))))
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
}),
}
tf.FakeDynamicClient.WatchReactionChain = nil
tf.FakeDynamicClient.AddWatchReactor("*", func(action cgtesting.Action) (handled bool, ret watch.Interface, err error) {
fw := watch.NewFake()
dep := &appsv1.Deployment{}
dep.Name = deploymentName
dep.Status = appsv1.DeploymentStatus{
Replicas: 1,
UpdatedReplicas: 1,
ReadyReplicas: 1,
AvailableReplicas: 1,
UnavailableReplicas: 0,
Conditions: []appsv1.DeploymentCondition{{
Type: appsv1.DeploymentAvailable,
}},
}
c, err := runtime.DefaultUnstructuredConverter.ToUnstructured(dep.DeepCopyObject())
if err != nil {
t.Errorf("unexpected err %s", err)
}
u := &unstructured.Unstructured{}
u.SetUnstructuredContent(c)
go fw.Add(u)
return true, fw, nil
})
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdRolloutStatus(tf, streams)
cmd.Flags().Set("watch", "false")
cmd.Run(cmd, []string{deploymentName})
expectedMsg := "deployment \"deployment/nginx-deployment\" successfully rolled out\n"
if buf.String() != expectedMsg {
t.Errorf("expected output: %s, but got: %s", expectedMsg, buf.String())
}
}
func TestRolloutStatusWatchDisabledUnavailable(t *testing.T) {
deploymentName := "deployment/nginx-deployment"
ns := scheme.Codecs.WithoutConversion()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
tf.ClientConfigVal = cmdtesting.DefaultClientConfig()
info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON)
encoder := ns.EncoderForVersion(info.Serializer, rolloutStatusGroupVersionEncoder)
tf.Client = &fake.RESTClient{
GroupVersion: rolloutStatusGroupVersionEncoder,
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
dep := &appsv1.Deployment{}
dep.Name = deploymentName
body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(encoder, dep))))
return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: body}, nil
}),
}
tf.FakeDynamicClient.WatchReactionChain = nil
tf.FakeDynamicClient.AddWatchReactor("*", func(action cgtesting.Action) (handled bool, ret watch.Interface, err error) {
fw := watch.NewFake()
dep := &appsv1.Deployment{}
dep.Name = deploymentName
dep.Status = appsv1.DeploymentStatus{
Replicas: 1,
UpdatedReplicas: 1,
ReadyReplicas: 1,
AvailableReplicas: 0,
UnavailableReplicas: 0,
Conditions: []appsv1.DeploymentCondition{{
Type: appsv1.DeploymentAvailable,
}},
}
c, err := runtime.DefaultUnstructuredConverter.ToUnstructured(dep.DeepCopyObject())
if err != nil {
t.Errorf("unexpected err %s", err)
}
u := &unstructured.Unstructured{}
u.SetUnstructuredContent(c)
go fw.Add(u)
return true, fw, nil
})
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdRolloutStatus(tf, streams)
cmd.Flags().Set("watch", "false")
cmd.Run(cmd, []string{deploymentName})
expectedMsg := "Waiting for deployment \"deployment/nginx-deployment\" rollout to finish: 0 of 1 updated replicas are available...\n"
if buf.String() != expectedMsg {
t.Errorf("expected output: %s, but got: %s", expectedMsg, buf.String())
}
}