...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/krmtotf/overrides_test.go

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

     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 krmtotf_test
    16  
    17  import (
    18  	"reflect"
    19  	"testing"
    20  
    21  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
    22  	. "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/krmtotf"
    23  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/hashicorp/terraform-provider-google-beta/google-beta"
    27  )
    28  
    29  func Test_FlattenComputeInstanceMetadata(t *testing.T) {
    30  	tests := []struct {
    31  		name     string
    32  		input    map[string]interface{}
    33  		expected map[string]interface{}
    34  	}{
    35  		{
    36  			name: "flattens structured list to simple map",
    37  			input: map[string]interface{}{
    38  				"key": "value",
    39  				"metadata": []interface{}{
    40  					map[string]interface{}{
    41  						"key":   "foo",
    42  						"value": "bar",
    43  					},
    44  					map[string]interface{}{
    45  						"key":   "bar",
    46  						"value": "baz",
    47  					},
    48  				},
    49  			},
    50  			expected: map[string]interface{}{
    51  				"key": "value",
    52  				"metadata": map[string]interface{}{
    53  					"foo": "bar",
    54  					"bar": "baz",
    55  				},
    56  			},
    57  		},
    58  		{
    59  			name: "no-op if no metadata given",
    60  			input: map[string]interface{}{
    61  				"key": "value",
    62  			},
    63  			expected: map[string]interface{}{
    64  				"key": "value",
    65  			},
    66  		},
    67  	}
    68  	for _, tc := range tests {
    69  		t.Run(tc.name, func(t *testing.T) {
    70  			output, err := FlattenComputeInstanceMetadata(tc.input)
    71  			if err != nil {
    72  				t.Fatalf("unexpected error: %v", err)
    73  			}
    74  			if !test.Equals(t, tc.expected, output) {
    75  				t.Fatalf("expected: %+v, actual: %+v", tc.expected, output)
    76  			}
    77  		})
    78  	}
    79  }
    80  
    81  func Test_ExpandComputeInstanceMetadata(t *testing.T) {
    82  	tests := []struct {
    83  		name     string
    84  		input    map[string]interface{}
    85  		prev     *Resource
    86  		expected map[string]interface{}
    87  	}{
    88  		{
    89  			name: "expands simple map to structured list",
    90  			input: map[string]interface{}{
    91  				"key": "value",
    92  				"metadata": map[string]interface{}{
    93  					"foo": "bar",
    94  					"bar": "baz",
    95  				},
    96  			},
    97  			prev: &Resource{
    98  				Resource: k8s.Resource{
    99  					Spec: map[string]interface{}{},
   100  				},
   101  			},
   102  			expected: map[string]interface{}{
   103  				"key": "value",
   104  				"metadata": []interface{}{
   105  					map[string]interface{}{
   106  						"key":   "bar",
   107  						"value": "baz",
   108  					},
   109  					map[string]interface{}{
   110  						"key":   "foo",
   111  						"value": "bar",
   112  					},
   113  				},
   114  			},
   115  		},
   116  		{
   117  			name: "previous value is source of truth",
   118  			input: map[string]interface{}{
   119  				"key": "value",
   120  				"metadata": map[string]interface{}{
   121  					"foo": "bar",
   122  					"bar": "baz",
   123  				},
   124  			},
   125  			prev: &Resource{
   126  				Resource: k8s.Resource{
   127  					Spec: map[string]interface{}{
   128  						"metadata": []interface{}{
   129  							map[string]interface{}{
   130  								"key":   "foo",
   131  								"value": "bar",
   132  							},
   133  							map[string]interface{}{
   134  								"key":   "bar",
   135  								"value": "baz",
   136  							},
   137  						},
   138  					},
   139  				},
   140  			},
   141  			expected: map[string]interface{}{
   142  				"key": "value",
   143  				"metadata": []interface{}{
   144  					map[string]interface{}{
   145  						"key":   "foo",
   146  						"value": "bar",
   147  					},
   148  					map[string]interface{}{
   149  						"key":   "bar",
   150  						"value": "baz",
   151  					},
   152  				},
   153  			},
   154  		},
   155  		{
   156  			name: "previous value is source of truth 2",
   157  			input: map[string]interface{}{
   158  				"key": "value",
   159  				"metadata": map[string]interface{}{
   160  					"foo": "bar",
   161  					"bar": "baz",
   162  					"baz": "abc",
   163  				},
   164  			},
   165  			prev: &Resource{
   166  				Resource: k8s.Resource{
   167  					Spec: map[string]interface{}{
   168  						"metadata": []interface{}{
   169  							map[string]interface{}{
   170  								"key":   "foo",
   171  								"value": "bar",
   172  							},
   173  							map[string]interface{}{
   174  								"key":   "bar",
   175  								"value": "baz",
   176  							},
   177  						},
   178  					},
   179  				},
   180  			},
   181  			expected: map[string]interface{}{
   182  				"key": "value",
   183  				"metadata": []interface{}{
   184  					map[string]interface{}{
   185  						"key":   "foo",
   186  						"value": "bar",
   187  					},
   188  					map[string]interface{}{
   189  						"key":   "bar",
   190  						"value": "baz",
   191  					},
   192  				},
   193  			},
   194  		},
   195  		{
   196  			name: "no-op if no metadata given",
   197  			input: map[string]interface{}{
   198  				"key": "value",
   199  			},
   200  			prev: &Resource{
   201  				Resource: k8s.Resource{
   202  					Spec: map[string]interface{}{},
   203  				},
   204  			},
   205  			expected: map[string]interface{}{
   206  				"key": "value",
   207  			},
   208  		},
   209  	}
   210  	for _, tc := range tests {
   211  		t.Run(tc.name, func(t *testing.T) {
   212  			output := ExpandComputeInstanceMetadata(tc.input, tc.prev)
   213  			if !test.Equals(t, tc.expected, output) {
   214  				t.Fatalf("unexpected diff in output (-want +got): \n%v", cmp.Diff(tc.expected, output))
   215  			}
   216  		})
   217  	}
   218  }
   219  
   220  func Test_MergeClusterConfigsFromLiveState(t *testing.T) {
   221  	t.Parallel()
   222  	resourceMap := google.ResourceMap()
   223  	tests := []struct {
   224  		name      string
   225  		config    map[string]interface{}
   226  		liveState map[string]interface{}
   227  		expected  map[string]interface{}
   228  	}{
   229  		{
   230  			name: "no changes on the existing clusters",
   231  			config: map[string]interface{}{
   232  				"cluster": []interface{}{
   233  					map[string]interface{}{
   234  						"cluster_id":   "test-c1",
   235  						"num_nodes":    float64(2),
   236  						"storage_type": "SSD",
   237  						"zone":         "us-west1-b",
   238  					},
   239  					map[string]interface{}{
   240  						"cluster_id": "test-c2",
   241  						"num_nodes":  float64(3),
   242  						"zone":       "us-east1-c",
   243  					},
   244  					map[string]interface{}{
   245  						"cluster_id":   "test-c3",
   246  						"num_nodes":    float64(1),
   247  						"storage_type": "SSD",
   248  						"zone":         "us-east1-b",
   249  					},
   250  				},
   251  			},
   252  			liveState: map[string]interface{}{
   253  				"cluster": []interface{}{
   254  					map[string]interface{}{
   255  						"cluster_id":   "test-c3",
   256  						"num_nodes":    float64(1),
   257  						"storage_type": "SSD",
   258  						"zone":         "us-east1-b",
   259  					},
   260  					map[string]interface{}{
   261  						"cluster_id":   "test-c1",
   262  						"num_nodes":    float64(2),
   263  						"storage_type": "SSD",
   264  						"zone":         "us-west1-b",
   265  					},
   266  					map[string]interface{}{
   267  						"cluster_id":   "test-c2",
   268  						"num_nodes":    float64(3),
   269  						"zone":         "us-east1-c",
   270  						"storage_type": "SSD",
   271  					},
   272  				},
   273  			},
   274  			expected: map[string]interface{}{
   275  				"cluster": []interface{}{
   276  					map[string]interface{}{
   277  						"cluster_id":   "test-c1",
   278  						"num_nodes":    float64(2),
   279  						"storage_type": "SSD",
   280  						"zone":         "us-west1-b",
   281  					},
   282  					map[string]interface{}{
   283  						"cluster_id":   "test-c2",
   284  						"num_nodes":    float64(3),
   285  						"storage_type": "SSD",
   286  						"zone":         "us-east1-c",
   287  					},
   288  					map[string]interface{}{
   289  						"cluster_id":   "test-c3",
   290  						"num_nodes":    float64(1),
   291  						"storage_type": "SSD",
   292  						"zone":         "us-east1-b",
   293  					},
   294  				},
   295  			},
   296  		},
   297  		{
   298  			name: "changes on the existing clusters are preserved",
   299  			config: map[string]interface{}{
   300  				"cluster": []interface{}{
   301  					map[string]interface{}{
   302  						"cluster_id":   "test-c1",
   303  						"num_nodes":    float64(3),
   304  						"storage_type": "SSD",
   305  						"zone":         "us-west1-b",
   306  					},
   307  					map[string]interface{}{
   308  						"cluster_id": "test-c2",
   309  						"num_nodes":  float64(3),
   310  						"zone":       "us-east1-c",
   311  					},
   312  					map[string]interface{}{
   313  						"cluster_id":   "test-c3",
   314  						"num_nodes":    float64(2),
   315  						"storage_type": "SSD",
   316  						"zone":         "us-east1-b",
   317  					},
   318  				},
   319  			},
   320  			liveState: map[string]interface{}{
   321  				"cluster": []interface{}{
   322  					map[string]interface{}{
   323  						"cluster_id":   "test-c3",
   324  						"num_nodes":    float64(1),
   325  						"storage_type": "SSD",
   326  						"zone":         "us-east1-b",
   327  					},
   328  					map[string]interface{}{
   329  						"cluster_id":   "test-c1",
   330  						"num_nodes":    float64(2),
   331  						"storage_type": "SSD",
   332  						"zone":         "us-west1-b",
   333  					},
   334  					map[string]interface{}{
   335  						"cluster_id":   "test-c2",
   336  						"num_nodes":    float64(3),
   337  						"zone":         "us-east1-c",
   338  						"storage_type": "SSD",
   339  					},
   340  				},
   341  			},
   342  			expected: map[string]interface{}{
   343  				"cluster": []interface{}{
   344  					map[string]interface{}{
   345  						"cluster_id":   "test-c1",
   346  						"num_nodes":    float64(3),
   347  						"storage_type": "SSD",
   348  						"zone":         "us-west1-b",
   349  					},
   350  					map[string]interface{}{
   351  						"cluster_id":   "test-c2",
   352  						"num_nodes":    float64(3),
   353  						"storage_type": "SSD",
   354  						"zone":         "us-east1-c",
   355  					},
   356  					map[string]interface{}{
   357  						"cluster_id":   "test-c3",
   358  						"num_nodes":    float64(2),
   359  						"storage_type": "SSD",
   360  						"zone":         "us-east1-b",
   361  					},
   362  				},
   363  			},
   364  		},
   365  		{
   366  			name: "omitted optional fields for the existing clusters are populated from live state",
   367  			config: map[string]interface{}{
   368  				"cluster": []interface{}{
   369  					map[string]interface{}{
   370  						"cluster_id": "test-c1",
   371  						"zone":       "us-west1-b",
   372  					},
   373  					map[string]interface{}{
   374  						"cluster_id": "test-c2",
   375  						"zone":       "us-east1-c",
   376  					},
   377  					map[string]interface{}{
   378  						"cluster_id": "test-c3",
   379  						"zone":       "us-east1-b",
   380  					},
   381  				},
   382  			},
   383  			liveState: map[string]interface{}{
   384  				"cluster": []interface{}{
   385  					map[string]interface{}{
   386  						"cluster_id":   "test-c3",
   387  						"num_nodes":    float64(1),
   388  						"storage_type": "SSD",
   389  						"zone":         "us-east1-b",
   390  					},
   391  					map[string]interface{}{
   392  						"cluster_id":   "test-c1",
   393  						"num_nodes":    float64(2),
   394  						"storage_type": "SSD",
   395  						"zone":         "us-west1-b",
   396  					},
   397  					map[string]interface{}{
   398  						"cluster_id":   "test-c2",
   399  						"num_nodes":    float64(3),
   400  						"zone":         "us-east1-c",
   401  						"storage_type": "SSD",
   402  					},
   403  				},
   404  			},
   405  			expected: map[string]interface{}{
   406  				"cluster": []interface{}{
   407  					map[string]interface{}{
   408  						"cluster_id":   "test-c1",
   409  						"num_nodes":    float64(2),
   410  						"storage_type": "SSD",
   411  						"zone":         "us-west1-b",
   412  					},
   413  					map[string]interface{}{
   414  						"cluster_id":   "test-c2",
   415  						"num_nodes":    float64(3),
   416  						"storage_type": "SSD",
   417  						"zone":         "us-east1-c",
   418  					},
   419  					map[string]interface{}{
   420  						"cluster_id":   "test-c3",
   421  						"num_nodes":    float64(1),
   422  						"storage_type": "SSD",
   423  						"zone":         "us-east1-b",
   424  					},
   425  				},
   426  			},
   427  		},
   428  		{
   429  			name: "remove an old cluster, add a new cluster and change an existing cluster",
   430  			config: map[string]interface{}{
   431  				"cluster": []interface{}{
   432  					map[string]interface{}{
   433  						"cluster_id": "test-c2",
   434  						"zone":       "us-east1-c",
   435  					},
   436  					map[string]interface{}{
   437  						"cluster_id": "test-c4",
   438  						"zone":       "us-east1-b",
   439  						"num_nodes":  float64(4),
   440  					},
   441  					map[string]interface{}{
   442  						"cluster_id": "test-c3",
   443  						"zone":       "us-east1-b",
   444  						"num_nodes":  float64(2),
   445  					},
   446  				},
   447  			},
   448  			liveState: map[string]interface{}{
   449  				"cluster": []interface{}{
   450  					map[string]interface{}{
   451  						"cluster_id":   "test-c3",
   452  						"num_nodes":    float64(1),
   453  						"storage_type": "SSD",
   454  						"zone":         "us-east1-b",
   455  					},
   456  					map[string]interface{}{
   457  						"cluster_id":   "test-c1",
   458  						"num_nodes":    float64(2),
   459  						"storage_type": "SSD",
   460  						"zone":         "us-west1-b",
   461  					},
   462  					map[string]interface{}{
   463  						"cluster_id":   "test-c2",
   464  						"num_nodes":    float64(3),
   465  						"zone":         "us-east1-c",
   466  						"storage_type": "SSD",
   467  					},
   468  				},
   469  			},
   470  			expected: map[string]interface{}{
   471  				"cluster": []interface{}{
   472  					map[string]interface{}{
   473  						"cluster_id":   "test-c2",
   474  						"num_nodes":    float64(3),
   475  						"storage_type": "SSD",
   476  						"zone":         "us-east1-c",
   477  					},
   478  					map[string]interface{}{
   479  						"cluster_id": "test-c4",
   480  						"zone":       "us-east1-b",
   481  						"num_nodes":  float64(4),
   482  					},
   483  					map[string]interface{}{
   484  						"cluster_id":   "test-c3",
   485  						"num_nodes":    float64(2),
   486  						"storage_type": "SSD",
   487  						"zone":         "us-east1-b",
   488  					},
   489  				},
   490  			},
   491  		},
   492  		{
   493  			name: "remove all old clusters",
   494  			config: map[string]interface{}{
   495  				"cluster": []interface{}{},
   496  			},
   497  			liveState: map[string]interface{}{
   498  				"cluster": []interface{}{
   499  					map[string]interface{}{
   500  						"cluster_id":   "test-c3",
   501  						"num_nodes":    float64(1),
   502  						"storage_type": "SSD",
   503  						"zone":         "us-east1-b",
   504  					},
   505  					map[string]interface{}{
   506  						"cluster_id":   "test-c1",
   507  						"num_nodes":    float64(2),
   508  						"storage_type": "SSD",
   509  						"zone":         "us-west1-b",
   510  					},
   511  					map[string]interface{}{
   512  						"cluster_id":   "test-c2",
   513  						"num_nodes":    float64(3),
   514  						"zone":         "us-east1-c",
   515  						"storage_type": "SSD",
   516  					},
   517  				},
   518  			},
   519  			expected: map[string]interface{}{
   520  				"cluster": []interface{}{},
   521  			},
   522  		},
   523  	}
   524  	for _, tc := range tests {
   525  		tc := tc
   526  		t.Run(tc.name, func(t *testing.T) {
   527  			res, err := MergeClusterConfigsFromLiveStateForBigtableInstance(tc.config, tc.liveState, resourceMap["google_bigtable_instance"])
   528  			if err != nil {
   529  				t.Fatalf("unexpected error: %v", err)
   530  			}
   531  			if !reflect.DeepEqual(res, tc.expected) {
   532  				diff := cmp.Diff(tc.expected, res)
   533  				t.Fatalf("The merged config has diff (-want, +got):\n%v", diff)
   534  			}
   535  		})
   536  	}
   537  }
   538  

View as plain text