github.com/kyma-project/kyma-environment-broker@v0.0.1/common/hyperscaler/shared_pool_test.go (about) 1 package hyperscaler 2 3 import ( 4 "testing" 5 6 "github.com/kyma-project/kyma-environment-broker/common/gardener" 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 corev1 "k8s.io/api/core/v1" 10 machineryv1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 12 "k8s.io/apimachinery/pkg/runtime" 13 ) 14 15 func TestSharedPool_SharedCredentialsSecretBinding(t *testing.T) { 16 17 for _, euAccess := range []bool{false, true} { 18 for _, testCase := range []struct { 19 description string 20 secretBindings []runtime.Object 21 shoots []runtime.Object 22 hyperscaler Type 23 expectedSecret string 24 }{ 25 { 26 description: "should get only Secret Bindings with proper hyperscaler", 27 secretBindings: []runtime.Object{ 28 newSecretBinding("sb1", "s1", "gcp", true, euAccess), 29 newSecretBinding("sb2", "s2", "azure", true, euAccess), 30 newSecretBinding("sb3", "s3", "aws", true, euAccess), 31 }, 32 shoots: []runtime.Object{ 33 newShoot("sh1", "sb1"), 34 newShoot("sh2", "sb1"), 35 newShoot("sh3", "sb1"), 36 newShoot("sh4", "sb2"), 37 }, 38 hyperscaler: "gcp", 39 expectedSecret: "s1", 40 }, 41 { 42 description: "should ignore not shared Secret Bindings", 43 secretBindings: []runtime.Object{ 44 newSecretBinding("sb1", "s1", "gcp", true, euAccess), 45 newSecretBinding("sb2", "s2", "gcp", false, euAccess), 46 newSecretBinding("sb3", "s3", "gcp", false, euAccess), 47 }, 48 shoots: []runtime.Object{ 49 newShoot("sh1", "sb1"), 50 newShoot("sh2", "sb1"), 51 newShoot("sh3", "sb1"), 52 newShoot("sh4", "sb2"), 53 }, 54 hyperscaler: "gcp", 55 expectedSecret: "s1", 56 }, 57 { 58 description: "should get least used Secret Binding for GCP", 59 secretBindings: []runtime.Object{ 60 newSecretBinding("sb1", "s1", "gcp", true, euAccess), 61 newSecretBinding("sb2", "s2", "gcp", true, euAccess), 62 newSecretBinding("sb3", "s3", "gcp", true, euAccess), 63 }, 64 shoots: []runtime.Object{ 65 newShoot("sh1", "sb1"), 66 newShoot("sh2", "sb1"), 67 newShoot("sh3", "sb1"), 68 newShoot("sh4", "sb2"), 69 newShoot("sh5", "sb2"), 70 newShoot("sh6", "sb3"), 71 }, 72 hyperscaler: "gcp", 73 expectedSecret: "s3", 74 }, 75 { 76 description: "should get least used Secret Binding for Azure", 77 secretBindings: []runtime.Object{ 78 newSecretBinding("sb1", "s1", "azure", true, euAccess), 79 newSecretBinding("sb2", "s2", "azure", true, euAccess), 80 newSecretBinding("sb3", "s3", "aws", true, euAccess), 81 }, 82 shoots: []runtime.Object{ 83 newShoot("sh1", "sb1"), 84 newShoot("sh2", "sb1"), 85 newShoot("sh3", "sb2"), 86 }, 87 hyperscaler: "azure", 88 expectedSecret: "s2", 89 }, 90 { 91 description: "should get least used Secret Binding for AWS", 92 secretBindings: []runtime.Object{ 93 newSecretBinding("sb1", "s1", "aws", true, euAccess), 94 newSecretBinding("sb2", "s2", "aws", true, euAccess), 95 }, 96 shoots: []runtime.Object{ 97 newShoot("sh1", "sb2"), 98 }, 99 hyperscaler: "aws", 100 expectedSecret: "s1", 101 }, 102 } { 103 t.Run(testCase.description, func(t *testing.T) { 104 // given 105 gardenerFake := gardener.NewDynamicFakeClient(append(testCase.shoots, testCase.secretBindings...)...) 106 pool := NewSharedGardenerAccountPool(gardenerFake, testNamespace) 107 108 // when 109 secretBinding, err := pool.SharedCredentialsSecretBinding(testCase.hyperscaler, euAccess) 110 require.NoError(t, err) 111 112 // then 113 assert.Equal(t, testCase.expectedSecret, secretBinding.GetSecretRefName()) 114 }) 115 } 116 } 117 } 118 119 func TestSharedPool_SharedCredentialsSecretBinding_Errors(t *testing.T) { 120 t.Run("should return error when no Secret Bindings for hyperscaler found", func(t *testing.T) { 121 // given 122 gardenerFake := gardener.NewDynamicFakeClient( 123 newSecretBinding("sb1", "s1", "azure", true, false), 124 newSecretBinding("sb2", "s2", "gcp", false, false), 125 ) 126 pool := NewSharedGardenerAccountPool(gardenerFake, testNamespace) 127 128 // when 129 _, err := pool.SharedCredentialsSecretBinding("gcp", false) 130 131 // then 132 require.Error(t, err) 133 assert.Contains(t, err.Error(), "no shared secret binding found") 134 }) 135 } 136 137 func newSecret(name string) *corev1.Secret { 138 return &corev1.Secret{ 139 ObjectMeta: machineryv1.ObjectMeta{ 140 Name: name, Namespace: testNamespace, 141 }, 142 Data: map[string][]byte{ 143 "credentials": []byte(name), 144 }, 145 } 146 } 147 148 func newSecretBinding(name, secretName, hyperscaler string, shared bool, euAccess bool) *unstructured.Unstructured { 149 secretBinding := &unstructured.Unstructured{ 150 Object: map[string]interface{}{ 151 "metadata": map[string]interface{}{ 152 "name": name, 153 "namespace": testNamespace, 154 "labels": map[string]interface{}{ 155 "hyperscalerType": hyperscaler, 156 }, 157 }, 158 "secretRef": map[string]interface{}{ 159 "name": secretName, 160 "namespace": testNamespace, 161 }, 162 }, 163 } 164 secretBinding.SetGroupVersionKind(secretBindingGVK) 165 166 if shared { 167 labels := secretBinding.GetLabels() 168 labels["shared"] = "true" 169 secretBinding.SetLabels(labels) 170 } 171 applyEuAccess(secretBinding, euAccess) 172 173 return secretBinding 174 } 175 176 func newShoot(name, secretBinding string) *unstructured.Unstructured { 177 shoot := &unstructured.Unstructured{ 178 Object: map[string]interface{}{ 179 "metadata": map[string]interface{}{ 180 "name": name, 181 "namespace": testNamespace, 182 }, 183 "spec": map[string]interface{}{ 184 "secretBindingName": secretBinding, 185 }, 186 }, 187 } 188 shoot.SetGroupVersionKind(shootGVK) 189 return shoot 190 }