github.com/GoogleContainerTools/skaffold/v2@v2.13.2/pkg/diag/validator/config_connector_test.go (about)

     1  /*
     2  Copyright 2021 The Skaffold Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package validator
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	"google.golang.org/protobuf/testing/protocmp"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    28  	"k8s.io/apimachinery/pkg/runtime/schema"
    29  	fakedynclient "k8s.io/client-go/dynamic/fake"
    30  	fakeclient "k8s.io/client-go/kubernetes/fake"
    31  	"k8s.io/kubectl/pkg/scheme"
    32  
    33  	"github.com/GoogleContainerTools/skaffold/v2/proto/v1"
    34  	"github.com/GoogleContainerTools/skaffold/v2/testutil"
    35  )
    36  
    37  func TestConfigConnectorValidator(t *testing.T) {
    38  	tests := []struct {
    39  		description string
    40  		status      map[string]interface{}
    41  		expected    []Resource
    42  	}{
    43  		{
    44  			description: "resource ready",
    45  			status: map[string]interface{}{
    46  				"status": "True",
    47  				"type":   "Ready",
    48  			},
    49  			expected: []Resource{
    50  				{
    51  					kind:   "bar",
    52  					name:   "foo1",
    53  					status: "Current",
    54  					ae:     &proto.ActionableErr{ErrCode: proto.StatusCode_STATUSCHECK_SUCCESS},
    55  				},
    56  			},
    57  		},
    58  		{
    59  			description: "resource in progress with message",
    60  			status: map[string]interface{}{
    61  				"status":  "False",
    62  				"type":    "Ready",
    63  				"message": "waiting on dependency",
    64  			},
    65  			expected: []Resource{
    66  				{
    67  					kind:   "bar",
    68  					name:   "foo1",
    69  					status: "InProgress",
    70  					ae:     &proto.ActionableErr{ErrCode: proto.StatusCode_STATUSCHECK_CONFIG_CONNECTOR_IN_PROGRESS, Message: "waiting on dependency"},
    71  				},
    72  			},
    73  		},
    74  		{
    75  			description: "resource in progress without message",
    76  			status: map[string]interface{}{
    77  				"status": "False",
    78  				"type":   "Ready",
    79  			},
    80  			expected: []Resource{
    81  				{
    82  					kind:   "bar",
    83  					name:   "foo1",
    84  					status: "InProgress",
    85  					ae:     &proto.ActionableErr{ErrCode: proto.StatusCode_STATUSCHECK_CONFIG_CONNECTOR_IN_PROGRESS},
    86  				},
    87  			},
    88  		},
    89  	}
    90  
    91  	for _, test := range tests {
    92  		testutil.Run(t, test.description, func(t *testutil.T) {
    93  			targetGvk := schema.GroupVersionKind{Version: "foo", Kind: "bar"}
    94  			obj := []map[string]interface{}{
    95  				{
    96  					"kind":       "bar",
    97  					"apiVersion": "foo",
    98  					"metadata":   map[string]interface{}{"name": "foo1"},
    99  					"status": map[string]interface{}{
   100  						"conditions": []interface{}{
   101  							test.status,
   102  						},
   103  					},
   104  				},
   105  			}
   106  			res := &unstructured.UnstructuredList{}
   107  			gvrs := map[schema.GroupVersionResource]string{}
   108  			for _, item := range obj {
   109  				obj := unstructured.Unstructured{Object: item}
   110  				gvk := obj.GroupVersionKind()
   111  				res.Items = append(res.Items, obj)
   112  				gvr := schema.GroupVersionResource{Group: gvk.Group, Version: gvk.Version, Resource: fmt.Sprintf("%ss", gvk.Kind)}
   113  				gvrs[gvr] = gvk.Kind + "List"
   114  			}
   115  
   116  			// Mock Kubernetes
   117  			client := fakeclient.NewSimpleClientset(res)
   118  			dynClient := fakedynclient.NewSimpleDynamicClientWithCustomListKinds(scheme.Scheme, gvrs, res)
   119  			for _, item := range res.Items {
   120  				gvk := item.GroupVersionKind()
   121  				client.Resources = append(client.Resources, &metav1.APIResourceList{
   122  					GroupVersion: item.GetObjectKind().GroupVersionKind().GroupVersion().String(),
   123  					APIResources: []metav1.APIResource{{
   124  						Kind:    gvk.Kind,
   125  						Version: gvk.Version,
   126  						Group:   gvk.Group,
   127  
   128  						Name: fmt.Sprintf("%ss", gvk.Kind),
   129  					}},
   130  				})
   131  				dynClient.Resources = append(dynClient.Resources, &metav1.APIResourceList{
   132  					GroupVersion: item.GetObjectKind().GroupVersionKind().GroupVersion().String(),
   133  					APIResources: []metav1.APIResource{{
   134  						Kind: item.GetObjectKind().GroupVersionKind().String(),
   135  						Name: item.GetName(),
   136  					}},
   137  				})
   138  				client.Tracker().Add(&item)
   139  			}
   140  			v := NewConfigConnectorValidator(client, dynClient, targetGvk)
   141  			r, err := v.Validate(context.Background(), "", metav1.ListOptions{})
   142  			t.CheckNoError(err)
   143  
   144  			t.CheckDeepEqual(test.expected, r, cmp.AllowUnexported(Resource{}), cmp.Comparer(func(x, y error) bool {
   145  				if x == nil && y == nil {
   146  					return true
   147  				} else if x != nil && y != nil {
   148  					return x.Error() == y.Error()
   149  				}
   150  				return false
   151  			}), protocmp.Transform())
   152  		})
   153  	}
   154  }