...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/resourceskeleton/resourceskeleton_test.go

Documentation: github.com/GoogleCloudPlatform/k8s-config-connector/pkg/resourceskeleton

     1  // Copyright 2022 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package resourceskeleton_test
    16  
    17  import (
    18  	"reflect"
    19  	"testing"
    20  
    21  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/core/v1alpha1"
    22  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/cli/asset"
    23  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/cli/serviceclient"
    24  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
    25  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/resourceskeleton"
    26  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/servicemapping/servicemappingloader"
    27  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/resourcefixture"
    28  	testservicemappingloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemappingloader"
    29  	testyaml "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/yaml"
    30  	tfprovider "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/tf/provider"
    31  
    32  	"github.com/google/go-cmp/cmp"
    33  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    34  )
    35  
    36  func TestNewProject(t *testing.T) {
    37  	projectId := "my-project-id"
    38  	u, err := resourceskeleton.NewProject(projectId, testservicemappingloader.New(t))
    39  	if err != nil {
    40  		t.Fatalf("unexpected error: %v", err)
    41  	}
    42  	if u.GetName() != projectId {
    43  		t.Fatalf("unexpected value for name: got '%v', want '%v'", u.GetName(), projectId)
    44  	}
    45  	expectedKind := "Project"
    46  	if u.GetKind() != expectedKind {
    47  		t.Fatalf("unexpected value for kind: got '%v', want '%v'", u.GetKind(), expectedKind)
    48  	}
    49  	if _, ok := k8s.GetAnnotation(k8s.FolderIDAnnotation, u); !ok {
    50  		t.Fatalf("expected annotations to contain the folder id annotation '%v'", k8s.ProjectIDAnnotation)
    51  	}
    52  }
    53  
    54  type URISkeletonTestCase struct {
    55  	ResourceConfigId string
    56  	URI              string
    57  	ExpectedSkeleton *unstructured.Unstructured
    58  }
    59  
    60  func TestNewFromURI(t *testing.T) {
    61  	tfProvider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
    62  	smLoader := testservicemappingloader.New(t)
    63  	idToRC := make(map[string]v1alpha1.ResourceConfig)
    64  	for _, sm := range smLoader.GetServiceMappings() {
    65  		for _, rc := range sm.Spec.Resources {
    66  			id := resourcefixture.GetUniqueResourceConfigId(rc)
    67  			idToRC[id] = rc
    68  		}
    69  	}
    70  	testCases := loadURISkeletonTestCases(t)
    71  	ensureURITCExistsForEachResourceConfig(t, smLoader, testCases)
    72  	for _, tc := range testCases {
    73  		rc := idToRC[tc.ResourceConfigId]
    74  		if !*rc.IDTemplateCanBeUsedToMatchResourceName {
    75  			continue
    76  		}
    77  		u, err := resourceskeleton.NewFromURI(tc.URI, smLoader, tfProvider)
    78  		if err != nil {
    79  			t.Fatalf("error getting skeleton unstruct from uri '%v': %v", tc.URI, err)
    80  		}
    81  		if !reflect.DeepEqual(tc.ExpectedSkeleton, u) {
    82  			diff := cmp.Diff(tc.ExpectedSkeleton, u)
    83  			t.Fatalf("mismatch between skeletons for resource id '%v', diff:\n%v", tc.ResourceConfigId, diff)
    84  		}
    85  	}
    86  }
    87  
    88  type AssetSkeletonTestCase struct {
    89  	ResourceConfigId string                     `json:"resourceConfigId,omitempty"`
    90  	Asset            *asset.Asset               `json:"asset,omitempty"`
    91  	ExpectedSkeleton *unstructured.Unstructured `json:"expectedSkeleton,omitempty"`
    92  }
    93  
    94  func TestNewFromAsset(t *testing.T) {
    95  	tfProvider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
    96  	smLoader := testservicemappingloader.New(t)
    97  	mockServiceClient := serviceclient.NewMockServiceClient(t)
    98  	testCases := loadAssetSkeletonTestCases(t)
    99  	ensureAssetTCExistsForEachResourceConfig(t, smLoader, testCases)
   100  	for _, tc := range testCases {
   101  		a := tc.Asset
   102  		if a == nil {
   103  			continue
   104  		}
   105  		u, err := resourceskeleton.NewFromAsset(a, smLoader, tfProvider, &mockServiceClient)
   106  		if err != nil {
   107  			t.Fatalf("error getting skeleton unstruct from asset '%v' with type '%v': %v", a.Name, a.AssetType, err)
   108  		}
   109  		if !reflect.DeepEqual(tc.ExpectedSkeleton, u) {
   110  			diff := cmp.Diff(tc.ExpectedSkeleton, u)
   111  			t.Fatalf("mismatch between skeletons for resource id '%v', diff:\n%v", tc.ResourceConfigId, diff)
   112  		}
   113  	}
   114  }
   115  
   116  func ensureAssetTCExistsForEachResourceConfig(t *testing.T, smLoader *servicemappingloader.ServiceMappingLoader, testCases []AssetSkeletonTestCase) {
   117  	t.Helper()
   118  	rcIdToTC := make(map[string]AssetSkeletonTestCase)
   119  	for _, tc := range testCases {
   120  		rcIdToTC[tc.ResourceConfigId] = tc
   121  	}
   122  	for _, sm := range smLoader.GetServiceMappings() {
   123  		for _, rc := range sm.Spec.Resources {
   124  			if rc.AutoGenerated {
   125  				continue
   126  			}
   127  			id := resourcefixture.GetUniqueResourceConfigId(rc)
   128  			if _, ok := rcIdToTC[id]; ok {
   129  				continue
   130  			}
   131  			t.Fatalf("missing test case for resource config with id '%v' and TF name '%v'", id, rc.Name)
   132  		}
   133  	}
   134  }
   135  
   136  func ensureURITCExistsForEachResourceConfig(t *testing.T, smLoader *servicemappingloader.ServiceMappingLoader, testCases []URISkeletonTestCase) {
   137  	t.Helper()
   138  	rcIdToTC := make(map[string]URISkeletonTestCase)
   139  	for _, tc := range testCases {
   140  		rcIdToTC[tc.ResourceConfigId] = tc
   141  	}
   142  	for _, sm := range smLoader.GetServiceMappings() {
   143  		for _, rc := range sm.Spec.Resources {
   144  			if rc.AutoGenerated {
   145  				continue
   146  			}
   147  			id := resourcefixture.GetUniqueResourceConfigId(rc)
   148  			if _, ok := rcIdToTC[id]; ok {
   149  				continue
   150  			}
   151  			t.Fatalf("missing test case for resource config with id '%v' and TF name '%v'", id, rc.Name)
   152  		}
   153  	}
   154  }
   155  
   156  const (
   157  	assetResourceSkeletonPath = "testdata/asset-skeleton.yaml"
   158  	uriResourceSkeletonPath   = "testdata/uri-skeleton.yaml"
   159  )
   160  
   161  func loadURISkeletonTestCases(t *testing.T) []URISkeletonTestCase {
   162  	var value []URISkeletonTestCase
   163  	testyaml.UnmarshalFile(t, uriResourceSkeletonPath, &value)
   164  	return value
   165  }
   166  
   167  func loadAssetSkeletonTestCases(t *testing.T) []AssetSkeletonTestCase {
   168  	var value []AssetSkeletonTestCase
   169  	testyaml.UnmarshalFile(t, assetResourceSkeletonPath, &value)
   170  	return value
   171  }
   172  

View as plain text