package resource import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" networkingv1beta1 "k8s.io/api/networking/v1beta1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "os" "testing" "github.com/aws/aws-sdk-go/aws" "github.com/stretchr/testify/assert" ) // TestCreateKubeConfig to test createKubeConfig func TestCreateKubeConfig(t *testing.T) { defer os.Remove(KubeConfigLocalPath) mockEKSSvc := &mockEKSClient{} mockSTSSvc := &mockSTSClient{} mockSMSvc := &mockSecretsManagerClient{} tests := map[string]struct { cluster, kubeconfig, role *string customKubeconfig []byte expectedErr string }{ "AllValues": { cluster: aws.String("eks"), kubeconfig: aws.String("arn:aws:secretsmanager:us-east-2:1234567890:secret:kubeconfig-Wt"), role: aws.String("arn:aws:iam::1234567890:role/TestRole"), expectedErr: "both ClusterID or KubeConfig can not be specified", }, "OnlyCluster": { cluster: aws.String("eks"), expectedErr: "", }, "ClusterWithRole": { cluster: aws.String("eks"), role: aws.String("arn:aws:iam::1234567890:role/TestRole"), expectedErr: "", }, "OnlySM": { kubeconfig: aws.String("arn:aws:secretsmanager:us-east-2:1234567890:secret:kubeconfig-Wt"), expectedErr: "", }, "NilValues": { expectedErr: "either ClusterID or KubeConfig must be specified", }, "CustomKubeconfig": { customKubeconfig: []byte("Test"), expectedErr: "", }, } for name, d := range tests { t.Run(name, func(t *testing.T) { err := createKubeConfig(mockEKSSvc, mockSTSSvc, mockSMSvc, d.cluster, d.kubeconfig, d.customKubeconfig) if err != nil { assert.Contains(t, err.Error(), d.expectedErr) } else { assert.FileExists(t, KubeConfigLocalPath) } }) } } // TestCreateNamespace to test createNamespace func TestCreateNamespace(t *testing.T) { c := NewMockClient(t, nil) err := c.createNamespace("test") assert.NoError(t, err) } // TestCheckPendingResources to test CheckPendingResources func TestCheckPendingResources(t *testing.T) { defer os.Remove(TempManifest) c := NewMockClient(t, nil) rd := &ReleaseData{ Name: "test", Namespace: "default", } tests := map[string]struct { assertion assert.BoolAssertionFunc manifest string }{ "Pending": { assertion: assert.True, manifest: TestPendingManifest, }, "NoPending": { assertion: assert.False, manifest: TestManifest, }, } for name, d := range tests { t.Run(name, func(t *testing.T) { rd.Manifest = d.manifest result, err := c.CheckPendingResources(rd) assert.Nil(t, err) d.assertion(t, result) }) } } // TestGetKubeResources to test GetKubeResources func TestGetKubeResources(t *testing.T) { defer os.Remove(TempManifest) c := NewMockClient(t, nil) manifest := `--- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment --- apiVersion: v1 kind: Service metadata: name: my-service --- apiVersion: v1 kind: Service metadata: name: lb-service spec: type: LoadBalancer` expectedMap := map[string]interface{}{ "Deployment": map[string]interface{}{ "nginx-deployment": map[string]interface{}{ "Namespace": "default", "Spec": interface{}(nil), "Status": map[string]interface{}{ "ReadyReplicas": "1", }, }, }, "Service": map[string]interface{}{ "lb-service": map[string]interface{}{ "Namespace": "default", "Spec": map[string]interface{}{ "ClusterIP": "127.0.0.1", "Type": "LoadBalancer", }, "Status": map[string]interface{}{ "LoadBalancer": map[string]interface{}{ "Ingress": []interface{}{ map[string]interface{}{ "Hostname": "elb.test.com", }, }, }, }, }, "my-service": map[string]interface{}{ "Namespace": "default", "Spec": map[string]interface{}{ "ClusterIP": "127.0.0.1", "Type": "ClusterIP", }, "Status": interface{}(nil), }, }, } rd := &ReleaseData{ Name: "test", Namespace: "default", Manifest: manifest, } result, err := c.GetKubeResources(rd) assert.Nil(t, err) assert.EqualValues(t, expectedMap, result) } // TestGetManifestDetails to test getManifestDetails func TestGetManifestDetails(t *testing.T) { defer os.Remove(TempManifest) c := NewMockClient(t, nil) rd := &ReleaseData{ Name: "test", Namespace: "default", Manifest: TestManifest, } _, err := c.getManifestDetails(rd) assert.Nil(t, err) } // TestReady to test ingressReady, volumeReady and deploymentReady func TestReady(t *testing.T) { tests := map[string]struct { assertion assert.BoolAssertionFunc ing *v1beta1.Ingress ingN *networkingv1beta1.Ingress pvc *corev1.PersistentVolumeClaim dep *appsv1.Deployment }{ "Pending": { assertion: assert.False, ing: ing("test-ingress", "default", true), ingN: ingN("test-ingressN", "default", true), pvc: vol("test-pvc", "default", true), dep: dep("test-dep", "default", true), }, "NoPending": { assertion: assert.True, ing: ing("test-ingress", "default", false), ingN: ingN("test-ingressN", "default", false), pvc: vol("test-pvc", "default", false), dep: dep("test-dep", "default", false), }, } for name, d := range tests { t.Run(name, func(t *testing.T) { result := ingressReady(d.ing) d.assertion(t, result) result = ingressNReady(d.ingN) d.assertion(t, result) result = volumeReady(d.pvc) d.assertion(t, result) result = deploymentReady(d.dep) d.assertion(t, result) }) } } // TestDaemonSetReadyReady to test daemonSetReady func TestDaemonSetReadyReady(t *testing.T) { tests := map[string]struct { assertion assert.BoolAssertionFunc ds *appsv1.DaemonSet }{ "Pending": { assertion: assert.False, ds: ds("test-ingress", "default", appsv1.RollingUpdateDaemonSetStrategyType, true), }, "NoPending": { assertion: assert.True, ds: ds("test-ingress", "default", appsv1.RollingUpdateDaemonSetStrategyType, false), }, "OnDeleteStrategy": { assertion: assert.True, ds: ds("test-ingress", "default", appsv1.OnDeleteDaemonSetStrategyType, false), }, } for name, d := range tests { t.Run(name, func(t *testing.T) { result := daemonSetReady(d.ds) d.assertion(t, result) }) } } // TestStatefulSetReady to test statefulSetReady func TestStatefulSetReady(t *testing.T) { tests := map[string]struct { assertion assert.BoolAssertionFunc ss *appsv1.StatefulSet }{ "Pending": { assertion: assert.False, ss: ss("test-ingress", "default", appsv1.RollingUpdateStatefulSetStrategyType, true), }, "NoPending": { assertion: assert.True, ss: ss("test-ingress", "default", appsv1.RollingUpdateStatefulSetStrategyType, false), }, "OnDeleteStrategy": { assertion: assert.True, ss: ss("test-ingress", "default", appsv1.OnDeleteStatefulSetStrategyType, false), }, } for name, d := range tests { t.Run(name, func(t *testing.T) { result := statefulSetReady(d.ss) d.assertion(t, result) }) } } func TestCrdReady(t *testing.T) { tests := map[string]struct { assertion assert.BoolAssertionFunc crd *apiextv1.CustomResourceDefinition }{ "Pending": { assertion: assert.False, crd: crd("test-crd", "default", false, true), }, "NoPending": { assertion: assert.True, crd: crd("test-crd", "default", false, false), }, "PendingWithNames": { assertion: assert.False, crd: crd("test-crd", "default", true, true), }, "NoPendingWithNames": { assertion: assert.True, crd: crd("test-crd", "default", true, false), }, } for name, d := range tests { t.Run(name, func(t *testing.T) { result := crdReady(d.crd) d.assertion(t, result) }) } } func TestCrdBetaReady(t *testing.T) { tests := map[string]struct { assertion assert.BoolAssertionFunc crd *apiextv1beta1.CustomResourceDefinition }{ "Pending": { assertion: assert.False, crd: crdBeta("test-crd", "default", false, true), }, "NoPending": { assertion: assert.True, crd: crdBeta("test-crd", "default", false, false), }, "PendingWithNames": { assertion: assert.False, crd: crdBeta("test-crd", "default", true, true), }, "NoPendingWithNames": { assertion: assert.True, crd: crdBeta("test-crd", "default", true, false), }, } for name, d := range tests { t.Run(name, func(t *testing.T) { result := crdBetaReady(d.crd) d.assertion(t, result) }) } }