...

Source file src/sigs.k8s.io/cli-utils/pkg/kstatus/polling/statusreaders/common_test.go

Documentation: sigs.k8s.io/cli-utils/pkg/kstatus/polling/statusreaders

     1  // Copyright 2020 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package statusreaders
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"sort"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  	appsv1 "k8s.io/api/apps/v1"
    15  	"k8s.io/apimachinery/pkg/api/errors"
    16  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    17  	"k8s.io/apimachinery/pkg/runtime/schema"
    18  	fakecr "sigs.k8s.io/cli-utils/pkg/kstatus/polling/clusterreader/fake"
    19  	fakesr "sigs.k8s.io/cli-utils/pkg/kstatus/polling/statusreaders/fake"
    20  	"sigs.k8s.io/cli-utils/pkg/kstatus/polling/testutil"
    21  	"sigs.k8s.io/cli-utils/pkg/object"
    22  	fakemapper "sigs.k8s.io/cli-utils/pkg/testutil"
    23  )
    24  
    25  var (
    26  	deploymentGVK = appsv1.SchemeGroupVersion.WithKind("Deployment")
    27  	deploymentGVR = appsv1.SchemeGroupVersion.WithResource("deployments")
    28  	replicaSetGVK = appsv1.SchemeGroupVersion.WithKind("ReplicaSet")
    29  
    30  	rsGVK = appsv1.SchemeGroupVersion.WithKind("ReplicaSet")
    31  )
    32  
    33  func TestLookupResource(t *testing.T) {
    34  	deploymentIdentifier := object.ObjMetadata{
    35  		GroupKind: deploymentGVK.GroupKind(),
    36  		Name:      "Foo",
    37  		Namespace: "Bar",
    38  	}
    39  
    40  	testCases := map[string]struct {
    41  		identifier         object.ObjMetadata
    42  		readerErr          error
    43  		expectErr          bool
    44  		expectedErrMessage string
    45  	}{
    46  		"unknown GVK": {
    47  			identifier: object.ObjMetadata{
    48  				GroupKind: schema.GroupKind{
    49  					Group: "custom.io",
    50  					Kind:  "Custom",
    51  				},
    52  				Name:      "Bar",
    53  				Namespace: "default",
    54  			},
    55  			expectErr:          true,
    56  			expectedErrMessage: `no matches for kind "Custom" in group "custom.io"`,
    57  		},
    58  		"resource does not exist": {
    59  			identifier:         deploymentIdentifier,
    60  			readerErr:          errors.NewNotFound(deploymentGVR.GroupResource(), "Foo"),
    61  			expectErr:          true,
    62  			expectedErrMessage: `deployments.apps "Foo" not found`,
    63  		},
    64  		"getting resource fails": {
    65  			identifier:         deploymentIdentifier,
    66  			readerErr:          errors.NewInternalError(fmt.Errorf("this is a test")),
    67  			expectErr:          true,
    68  			expectedErrMessage: "Internal error occurred: this is a test",
    69  		},
    70  		"getting resource succeeds": {
    71  			identifier: deploymentIdentifier,
    72  		},
    73  		"context cancelled": {
    74  			identifier:         deploymentIdentifier,
    75  			readerErr:          context.Canceled,
    76  			expectErr:          true,
    77  			expectedErrMessage: context.Canceled.Error(),
    78  		},
    79  	}
    80  
    81  	for tn, tc := range testCases {
    82  		t.Run(tn, func(t *testing.T) {
    83  			fakeReader := &fakecr.ClusterReader{
    84  				GetErr: tc.readerErr,
    85  			}
    86  			fakeMapper := fakemapper.NewFakeRESTMapper(deploymentGVK)
    87  
    88  			statusReader := &baseStatusReader{
    89  				mapper: fakeMapper,
    90  			}
    91  
    92  			u, err := statusReader.lookupResource(context.Background(), fakeReader, tc.identifier)
    93  
    94  			if tc.expectErr {
    95  				if err == nil {
    96  					t.Errorf("expected error, but didn't get one")
    97  				} else {
    98  					assert.EqualError(t, err, tc.expectedErrMessage)
    99  				}
   100  				return
   101  			}
   102  
   103  			require.NoError(t, err)
   104  
   105  			assert.Equal(t, deploymentGVK, u.GroupVersionKind())
   106  		})
   107  	}
   108  }
   109  
   110  func TestStatusForGeneratedResources(t *testing.T) {
   111  	testCases := map[string]struct {
   112  		manifest    string
   113  		listObjects []unstructured.Unstructured
   114  		listErr     error
   115  		gk          schema.GroupKind
   116  		path        []string
   117  		expectError bool
   118  		errMessage  string
   119  	}{
   120  		"invalid selector": {
   121  			manifest: `
   122  apiVersion: apps/v1
   123  kind: Deployment
   124  metadata:
   125    name: Foo
   126  spec:
   127    replicas: 1
   128  `,
   129  			gk:          appsv1.SchemeGroupVersion.WithKind("ReplicaSet").GroupKind(),
   130  			path:        []string{"spec", "selector"},
   131  			expectError: true,
   132  			errMessage:  "no selector found",
   133  		},
   134  		"Invalid GVK": {
   135  			manifest: `
   136  apiVersion: apps/v1
   137  kind: Deployment
   138  metadata:
   139    name: Foo
   140  spec:
   141    replicas: 1
   142    selector:
   143      matchLabels:
   144        app: nginx
   145  `,
   146  			gk: schema.GroupKind{
   147  				Group: "custom.io",
   148  				Kind:  "Custom",
   149  			},
   150  			path:        []string{"spec", "selector"},
   151  			expectError: true,
   152  			errMessage:  `no matches for kind "Custom" in group "custom.io"`,
   153  		},
   154  		"error listing replicasets": {
   155  			manifest: `
   156  apiVersion: apps/v1
   157  kind: Deployment
   158  metadata:
   159    name: Foo
   160  spec:
   161    replicas: 1
   162    selector:
   163      matchLabels:
   164        app: nginx
   165  `,
   166  			listErr:     fmt.Errorf("this is a test"),
   167  			gk:          appsv1.SchemeGroupVersion.WithKind("ReplicaSet").GroupKind(),
   168  			path:        []string{"spec", "selector"},
   169  			expectError: true,
   170  			errMessage:  "this is a test",
   171  		},
   172  		"successfully lists and polling the generated resources": {
   173  			manifest: `
   174  apiVersion: apps/v1
   175  kind: Deployment
   176  metadata:
   177    name: Foo
   178  spec:
   179    replicas: 1
   180    selector:
   181      matchLabels:
   182        app: nginx
   183  `,
   184  			listObjects: []unstructured.Unstructured{
   185  				{
   186  					Object: map[string]interface{}{
   187  						"apiVersion": "apps/v1",
   188  						"kind":       "ReplicaSet",
   189  						"metadata": map[string]interface{}{
   190  							"name":      "Foo-12345",
   191  							"namespace": "default",
   192  						},
   193  					},
   194  				},
   195  			},
   196  			gk:          appsv1.SchemeGroupVersion.WithKind("ReplicaSet").GroupKind(),
   197  			path:        []string{"spec", "selector"},
   198  			expectError: false,
   199  		},
   200  	}
   201  
   202  	for tn, tc := range testCases {
   203  		t.Run(tn, func(t *testing.T) {
   204  			fakeClusterReader := &fakecr.ClusterReader{
   205  				ListResources: &unstructured.UnstructuredList{
   206  					Items: tc.listObjects,
   207  				},
   208  				ListErr: tc.listErr,
   209  			}
   210  			fakeMapper := fakemapper.NewFakeRESTMapper(rsGVK)
   211  			fakeStatusReader := &fakesr.StatusReader{}
   212  
   213  			object := testutil.YamlToUnstructured(t, tc.manifest)
   214  
   215  			resourceStatuses, err := statusForGeneratedResources(context.Background(), fakeMapper, fakeClusterReader,
   216  				fakeStatusReader, object, tc.gk, tc.path...)
   217  
   218  			if tc.expectError {
   219  				if err == nil {
   220  					t.Errorf("expected an error, but didn't get one")
   221  					return
   222  				}
   223  				assert.EqualError(t, err, tc.errMessage)
   224  				return
   225  			}
   226  			if !tc.expectError && err != nil {
   227  				t.Errorf("did not expect an error, but got %v", err)
   228  			}
   229  
   230  			assert.Len(t, resourceStatuses, len(tc.listObjects))
   231  			assert.True(t, sort.IsSorted(resourceStatuses))
   232  		})
   233  	}
   234  }
   235  

View as plain text