github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/broker/instance_create_test.go (about) 1 package broker_test 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 "testing" 9 10 "github.com/kyma-project/kyma-environment-broker/internal/euaccess" 11 12 "github.com/pivotal-cf/brokerapi/v8/domain/apiresponses" 13 14 "github.com/kyma-project/control-plane/components/provisioner/pkg/gqlschema" 15 "github.com/kyma-project/kyma-environment-broker/common/gardener" 16 "github.com/kyma-project/kyma-environment-broker/internal" 17 "github.com/kyma-project/kyma-environment-broker/internal/broker" 18 "github.com/kyma-project/kyma-environment-broker/internal/broker/automock" 19 "github.com/kyma-project/kyma-environment-broker/internal/dashboard" 20 "github.com/kyma-project/kyma-environment-broker/internal/fixture" 21 "github.com/kyma-project/kyma-environment-broker/internal/middleware" 22 "github.com/kyma-project/kyma-environment-broker/internal/ptr" 23 "github.com/kyma-project/kyma-environment-broker/internal/storage" 24 "github.com/pivotal-cf/brokerapi/v8/domain" 25 "github.com/sirupsen/logrus" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/mock" 28 "github.com/stretchr/testify/require" 29 ) 30 31 const ( 32 serviceID = "47c9dcbf-ff30-448e-ab36-d3bad66ba281" 33 planID = "4deee563-e5ec-4731-b9b1-53b42d855f0c" 34 globalAccountID = "e8f7ec0a-0cd6-41f0-905d-5d1efa9fb6c4" 35 whitelistedGlobalAccountID = "whitelisted-global-account-id" 36 subAccountID = "3cb65e5b-e455-4799-bf35-be46e8f5a533" 37 userID = "test@test.pl" 38 39 instanceID = "d3d5dca4-5dc8-44ee-a825-755c2a3fb839" 40 otherInstanceID = "87bfaeaa-48eb-40d6-84f3-3d5368eed3eb" 41 existOperationID = "920cbfd9-24e9-4aa2-aa77-879e9aabe140" 42 clusterName = "cluster-testing" 43 region = "eu" 44 brokerURL = "example.com" 45 notEncodedKubeconfig = "apiVersion: v1\\nkind: Config" 46 encodedKubeconfig = "YXBpVmVyc2lvbjogdjEKa2luZDogQ29uZmlnCmN1cnJlbnQtY29udGV4dDogc2hvb3QtLWt5bWEtZGV2LS1jbHVzdGVyLW5hbWUKY29udGV4dHM6CiAgLSBuYW1lOiBzaG9vdC0ta3ltYS1kZXYtLWNsdXN0ZXItbmFtZQogICAgY29udGV4dDoKICAgICAgY2x1c3Rlcjogc2hvb3QtLWt5bWEtZGV2LS1jbHVzdGVyLW5hbWUKICAgICAgdXNlcjogc2hvb3QtLWt5bWEtZGV2LS1jbHVzdGVyLW5hbWUtdG9rZW4KY2x1c3RlcnM6CiAgLSBuYW1lOiBzaG9vdC0ta3ltYS1kZXYtLWNsdXN0ZXItbmFtZQogICAgY2x1c3RlcjoKICAgICAgc2VydmVyOiBodHRwczovL2FwaS5jbHVzdGVyLW5hbWUua3ltYS1kZXYuc2hvb3QuY2FuYXJ5Lms4cy1oYW5hLm9uZGVtYW5kLmNvbQogICAgICBjZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YTogPi0KICAgICAgICBMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHQKdXNlcnM6CiAgLSBuYW1lOiBzaG9vdC0ta3ltYS1kZXYtLWNsdXN0ZXItbmFtZS10b2tlbgogICAgdXNlcjoKICAgICAgdG9rZW46ID4tCiAgICAgICAgdE9rRW4K" 47 shootName = "own-cluster-name" 48 shootDomain = "kyma-dev.shoot.canary.k8s-hana.ondemand.com" 49 ) 50 51 var dashboardConfig = dashboard.Config{LandscapeURL: "https://dashboard.example.com"} 52 53 func TestProvision_Provision(t *testing.T) { 54 t.Run("new operation will be created", func(t *testing.T) { 55 // given 56 // #setup memory storage 57 memoryStorage := storage.NewMemoryStorage() 58 59 queue := &automock.Queue{} 60 queue.On("Add", mock.AnythingOfType("string")) 61 62 factoryBuilder := &automock.PlanValidator{} 63 factoryBuilder.On("IsPlanSupport", planID).Return(true) 64 65 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 66 return &gqlschema.ClusterConfigInput{}, nil 67 } 68 // #create provisioner endpoint 69 provisionEndpoint := broker.NewProvision( 70 broker.Config{ 71 EnablePlans: []string{"gcp", "azure"}, 72 URL: brokerURL, 73 OnlySingleTrialPerGA: true, 74 EnableKubeconfigURLLabel: true, 75 }, 76 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 77 memoryStorage.Operations(), 78 memoryStorage.Instances(), 79 queue, 80 factoryBuilder, 81 broker.PlansConfig{}, 82 false, 83 planDefaults, 84 euaccess.WhitelistSet{}, 85 "request rejected, your globalAccountId is not whitelisted", 86 logrus.StandardLogger(), 87 dashboardConfig, 88 ) 89 90 // when 91 response, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 92 ServiceID: serviceID, 93 PlanID: planID, 94 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 95 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 96 }, true) 97 t.Logf("%+v\n", *provisionEndpoint) 98 99 // then 100 require.NoError(t, err) 101 assert.Regexp(t, "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$", response.OperationData) 102 assert.NotEqual(t, instanceID, response.OperationData) 103 assert.Regexp(t, `^https:\/\/dashboard\.example\.com\/\?kubeconfigID=`, response.DashboardURL) 104 assert.Equal(t, clusterName, response.Metadata.Labels["Name"]) 105 assert.Equal(t, fmt.Sprintf("https://%s/kubeconfig/%s", brokerURL, instanceID), response.Metadata.Labels["KubeconfigURL"]) 106 107 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 108 require.NoError(t, err) 109 assert.Equal(t, operation.InstanceID, instanceID) 110 111 assert.Equal(t, globalAccountID, operation.ProvisioningParameters.ErsContext.GlobalAccountID) 112 assert.Equal(t, clusterName, operation.ProvisioningParameters.Parameters.Name) 113 assert.Equal(t, userID, operation.ProvisioningParameters.ErsContext.UserID) 114 assert.Equal(t, "req-region", operation.ProvisioningParameters.PlatformRegion) 115 116 assert.Equal(t, fixDNSProviders(), operation.ShootDNSProviders) 117 118 instance, err := memoryStorage.Instances().GetByID(instanceID) 119 require.NoError(t, err) 120 121 assert.Equal(t, instance.Parameters, operation.ProvisioningParameters) 122 assert.Regexp(t, `^https:\/\/dashboard\.example\.com\/\?kubeconfigID=`, response.DashboardURL) 123 assert.Equal(t, instance.GlobalAccountID, globalAccountID) 124 assert.Equal(t, fixDNSProviders(), instance.InstanceDetails.ShootDNSProviders) 125 }) 126 127 t.Run("new operation for own_cluster plan with kubeconfig will be created", func(t *testing.T) { 128 // given 129 // #setup memory storage 130 memoryStorage := storage.NewMemoryStorage() 131 132 queue := &automock.Queue{} 133 queue.On("Add", mock.AnythingOfType("string")) 134 135 factoryBuilder := &automock.PlanValidator{} 136 factoryBuilder.On("IsPlanSupport", broker.OwnClusterPlanID).Return(true) 137 138 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 139 return &gqlschema.ClusterConfigInput{}, nil 140 } 141 // #create provisioner endpoint 142 provisionEndpoint := broker.NewProvision( 143 broker.Config{ 144 EnablePlans: []string{"gcp", "azure", "own_cluster"}, 145 URL: brokerURL, 146 OnlySingleTrialPerGA: true, 147 EnableKubeconfigURLLabel: true, 148 }, 149 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 150 memoryStorage.Operations(), 151 memoryStorage.Instances(), 152 queue, 153 factoryBuilder, 154 broker.PlansConfig{}, 155 false, 156 planDefaults, 157 euaccess.WhitelistSet{}, 158 "request rejected, your globalAccountId is not whitelisted", 159 logrus.StandardLogger(), 160 dashboardConfig, 161 ) 162 163 // when 164 response, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 165 ServiceID: serviceID, 166 PlanID: broker.OwnClusterPlanID, 167 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s", "kubeconfig": "%s", "shootName":"%s", "shootDomain":"%s"}`, clusterName, encodedKubeconfig, shootName, shootDomain)), 168 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 169 }, true) 170 t.Logf("%+v\n", *provisionEndpoint) 171 172 // then 173 require.NoError(t, err) 174 // UUID with version 4 and variant 1 i.e RFC. 4122/DCE 175 assert.Regexp(t, "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$", response.OperationData) 176 assert.NotEqual(t, instanceID, response.OperationData) 177 assert.Equal(t, `https://dashboard.example.com`, response.DashboardURL) 178 assert.Equal(t, clusterName, response.Metadata.Labels["Name"]) 179 assert.NotContains(t, response.Metadata.Labels, "KubeconfigURL") 180 181 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 182 require.NoError(t, err) 183 assert.Equal(t, operation.InstanceID, instanceID) 184 185 assert.Equal(t, globalAccountID, operation.ProvisioningParameters.ErsContext.GlobalAccountID) 186 assert.Equal(t, clusterName, operation.ProvisioningParameters.Parameters.Name) 187 assert.Equal(t, userID, operation.ProvisioningParameters.ErsContext.UserID) 188 assert.Equal(t, "req-region", operation.ProvisioningParameters.PlatformRegion) 189 190 require.NoError(t, err) 191 192 assert.Equal(t, fixDNSProviders(), operation.ShootDNSProviders) 193 194 instance, err := memoryStorage.Instances().GetByID(instanceID) 195 require.NoError(t, err) 196 197 assert.Equal(t, instance.Parameters, operation.ProvisioningParameters) 198 assert.Equal(t, `https://dashboard.example.com`, response.DashboardURL) 199 assert.Equal(t, instance.GlobalAccountID, globalAccountID) 200 assert.Equal(t, fixDNSProviders(), instance.InstanceDetails.ShootDNSProviders) 201 assert.Equal(t, shootDomain, operation.ShootDomain) 202 }) 203 204 t.Run("new operation for own_cluster plan with not encoded kubeconfig will not be created", func(t *testing.T) { 205 // given 206 // #setup memory storage 207 memoryStorage := storage.NewMemoryStorage() 208 209 queue := &automock.Queue{} 210 queue.On("Add", mock.AnythingOfType("string")) 211 212 factoryBuilder := &automock.PlanValidator{} 213 factoryBuilder.On("IsPlanSupport", broker.OwnClusterPlanID).Return(true) 214 215 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 216 return &gqlschema.ClusterConfigInput{}, nil 217 } 218 // #create provisioner endpoint 219 provisionEndpoint := broker.NewProvision( 220 broker.Config{ 221 EnablePlans: []string{"gcp", "azure", "own_cluster"}, 222 URL: brokerURL, 223 OnlySingleTrialPerGA: true, 224 EnableKubeconfigURLLabel: true, 225 }, 226 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 227 memoryStorage.Operations(), 228 memoryStorage.Instances(), 229 queue, 230 factoryBuilder, 231 broker.PlansConfig{}, 232 false, 233 planDefaults, 234 euaccess.WhitelistSet{}, 235 "request rejected, your globalAccountId is not whitelisted", 236 logrus.StandardLogger(), 237 dashboardConfig, 238 ) 239 240 // when 241 _, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 242 ServiceID: serviceID, 243 PlanID: broker.OwnClusterPlanID, 244 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s", "kubeconfig": "%s", "shootName":"%s", "shootDomain":"%s"}`, clusterName, notEncodedKubeconfig, shootName, shootDomain)), 245 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 246 }, true) 247 t.Logf("%+v\n", *provisionEndpoint) 248 249 // then 250 assert.ErrorContains(t, err, "while decoding kubeconfig") 251 }) 252 253 t.Run("new operation for own_cluster plan will not be created without required fields", func(t *testing.T) { 254 // given 255 // #setup memory storage 256 memoryStorage := storage.NewMemoryStorage() 257 258 queue := &automock.Queue{} 259 queue.On("Add", mock.AnythingOfType("string")) 260 261 factoryBuilder := &automock.PlanValidator{} 262 factoryBuilder.On("IsPlanSupport", broker.OwnClusterPlanID).Return(true) 263 264 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 265 return &gqlschema.ClusterConfigInput{}, nil 266 } 267 // #create provisioner endpoint 268 provisionEndpoint := broker.NewProvision( 269 broker.Config{ 270 EnablePlans: []string{"gcp", "azure", "own_cluster"}, 271 URL: brokerURL, 272 OnlySingleTrialPerGA: true, 273 EnableKubeconfigURLLabel: true, 274 }, 275 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 276 memoryStorage.Operations(), 277 memoryStorage.Instances(), 278 queue, 279 factoryBuilder, 280 broker.PlansConfig{}, 281 false, 282 planDefaults, 283 euaccess.WhitelistSet{}, 284 "request rejected, your globalAccountId is not whitelisted", 285 logrus.StandardLogger(), 286 dashboardConfig, 287 ) 288 289 // when shootDomain is missing 290 _, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 291 ServiceID: serviceID, 292 PlanID: broker.OwnClusterPlanID, 293 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s", "kubeconfig": "%s", "shootName":"%s"}`, clusterName, encodedKubeconfig, shootName)), 294 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 295 }, true) 296 t.Logf("%+v\n", *provisionEndpoint) 297 298 // then 299 assert.ErrorContains(t, err, "while validating input parameters: (root): shootDomain is required") 300 301 // when shootName is missing 302 _, err = provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 303 ServiceID: serviceID, 304 PlanID: broker.OwnClusterPlanID, 305 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s", "kubeconfig": "%s", "shootDomain":"%s"}`, clusterName, encodedKubeconfig, shootDomain)), 306 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 307 }, true) 308 t.Logf("%+v\n", *provisionEndpoint) 309 310 // then 311 assert.ErrorContains(t, err, "while validating input parameters: (root): shootName is required") 312 313 // when shootDomain is missing 314 _, err = provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 315 ServiceID: serviceID, 316 PlanID: broker.OwnClusterPlanID, 317 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s", "shootDomain": "%s", "shootName":"%s"}`, clusterName, shootDomain, shootName)), 318 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 319 }, true) 320 t.Logf("%+v\n", *provisionEndpoint) 321 322 // then 323 assert.ErrorContains(t, err, "while validating input parameters: (root): kubeconfig is required") 324 }) 325 326 t.Run("for plan other than own_cluster invalid kubeconfig will be ignored", func(t *testing.T) { 327 // given 328 // #setup memory storage 329 memoryStorage := storage.NewMemoryStorage() 330 331 queue := &automock.Queue{} 332 queue.On("Add", mock.AnythingOfType("string")) 333 334 factoryBuilder := &automock.PlanValidator{} 335 factoryBuilder.On("IsPlanSupport", planID).Return(true) 336 337 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 338 return &gqlschema.ClusterConfigInput{}, nil 339 } 340 // #create provisioner endpoint 341 provisionEndpoint := broker.NewProvision( 342 broker.Config{ 343 EnablePlans: []string{"gcp", "azure"}, 344 URL: brokerURL, 345 OnlySingleTrialPerGA: true, 346 EnableKubeconfigURLLabel: true, 347 }, 348 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 349 memoryStorage.Operations(), 350 memoryStorage.Instances(), 351 queue, 352 factoryBuilder, 353 broker.PlansConfig{}, 354 false, 355 planDefaults, 356 euaccess.WhitelistSet{}, 357 "request rejected, your globalAccountId is not whitelisted", 358 logrus.StandardLogger(), 359 dashboardConfig, 360 ) 361 362 // when 363 response, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 364 ServiceID: serviceID, 365 PlanID: planID, 366 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s", "kubeconfig": "%s", "shootName":"%s", "shootDomain":"%s"}`, clusterName, notEncodedKubeconfig, shootName, shootDomain)), 367 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 368 }, true) 369 t.Logf("%+v\n", *provisionEndpoint) 370 371 // then 372 require.NoError(t, err) 373 // UUID with version 4 and variant 1 i.e RFC. 4122/DCE 374 assert.Regexp(t, "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$", response.OperationData) 375 assert.NotEqual(t, instanceID, response.OperationData) 376 assert.Regexp(t, `^https:\/\/dashboard\.example\.com\/\?kubeconfigID=`, response.DashboardURL) 377 assert.Equal(t, clusterName, response.Metadata.Labels["Name"]) 378 assert.Equal(t, fmt.Sprintf("https://%s/kubeconfig/%s", brokerURL, instanceID), response.Metadata.Labels["KubeconfigURL"]) 379 380 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 381 require.NoError(t, err) 382 assert.Equal(t, operation.InstanceID, instanceID) 383 384 assert.Equal(t, globalAccountID, operation.ProvisioningParameters.ErsContext.GlobalAccountID) 385 assert.Equal(t, clusterName, operation.ProvisioningParameters.Parameters.Name) 386 assert.Equal(t, userID, operation.ProvisioningParameters.ErsContext.UserID) 387 assert.Equal(t, "req-region", operation.ProvisioningParameters.PlatformRegion) 388 389 require.NoError(t, err) 390 391 assert.Equal(t, fixDNSProviders(), operation.ShootDNSProviders) 392 393 instance, err := memoryStorage.Instances().GetByID(instanceID) 394 require.NoError(t, err) 395 396 assert.Equal(t, instance.Parameters, operation.ProvisioningParameters) 397 assert.Regexp(t, `^https:\/\/dashboard\.example\.com\/\?kubeconfigID=`, response.DashboardURL) 398 assert.Equal(t, instance.GlobalAccountID, globalAccountID) 399 assert.Equal(t, fixDNSProviders(), instance.InstanceDetails.ShootDNSProviders) 400 }) 401 402 t.Run("existing operation ID will be return", func(t *testing.T) { 403 // given 404 // #setup memory storage 405 memoryStorage := storage.NewMemoryStorage() 406 err := memoryStorage.Operations().InsertOperation(fixExistOperation()) 407 assert.NoError(t, err) 408 err = memoryStorage.Instances().Insert(fixInstance()) 409 410 factoryBuilder := &automock.PlanValidator{} 411 factoryBuilder.On("IsPlanSupport", planID).Return(true) 412 413 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 414 return &gqlschema.ClusterConfigInput{}, nil 415 } 416 // #create provisioner endpoint 417 provisionEndpoint := broker.NewProvision( 418 broker.Config{ 419 EnablePlans: []string{"gcp", "azure", "azure_lite"}, 420 OnlySingleTrialPerGA: true, 421 EnableKubeconfigURLLabel: true, 422 }, 423 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 424 memoryStorage.Operations(), 425 memoryStorage.Instances(), 426 nil, 427 factoryBuilder, 428 broker.PlansConfig{}, 429 false, 430 planDefaults, 431 euaccess.WhitelistSet{}, 432 "request rejected, your globalAccountId is not whitelisted", 433 logrus.StandardLogger(), 434 dashboardConfig, 435 ) 436 437 // when 438 response, err := provisionEndpoint.Provision(fixRequestContext(t, region), instanceID, domain.ProvisionDetails{ 439 ServiceID: serviceID, 440 PlanID: planID, 441 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 442 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, userID)), 443 }, true) 444 445 // then 446 require.NoError(t, err) 447 assert.Equal(t, existOperationID, response.OperationData) 448 assert.Len(t, response.Metadata.Labels, 2) 449 }) 450 451 t.Run("more than one trial is not allowed", func(t *testing.T) { 452 // given 453 memoryStorage := storage.NewMemoryStorage() 454 err := memoryStorage.Operations().InsertOperation(fixExistOperation()) 455 assert.NoError(t, err) 456 err = memoryStorage.Instances().Insert(internal.Instance{ 457 InstanceID: instanceID, 458 GlobalAccountID: globalAccountID, 459 ServiceID: serviceID, 460 ServicePlanID: broker.TrialPlanID, 461 }) 462 assert.NoError(t, err) 463 464 factoryBuilder := &automock.PlanValidator{} 465 factoryBuilder.On("IsPlanSupport", broker.TrialPlanID).Return(true) 466 467 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 468 return &gqlschema.ClusterConfigInput{}, nil 469 } 470 provisionEndpoint := broker.NewProvision( 471 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite", broker.TrialPlanName}, OnlySingleTrialPerGA: true}, 472 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 473 memoryStorage.Operations(), 474 memoryStorage.Instances(), 475 nil, 476 factoryBuilder, 477 broker.PlansConfig{}, 478 false, 479 planDefaults, 480 euaccess.WhitelistSet{}, 481 "request rejected, your globalAccountId is not whitelisted", 482 logrus.StandardLogger(), 483 dashboardConfig, 484 ) 485 486 // when 487 _, err = provisionEndpoint.Provision(fixRequestContext(t, "dummy"), "new-instance-id", domain.ProvisionDetails{ 488 ServiceID: serviceID, 489 PlanID: broker.TrialPlanID, 490 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 491 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, userID)), 492 }, true) 493 494 // then 495 assert.EqualError(t, err, "trial Kyma was created for the global account, but there is only one allowed") 496 }) 497 498 t.Run("more than one trial is allowed", func(t *testing.T) { 499 // given 500 memoryStorage := storage.NewMemoryStorage() 501 err := memoryStorage.Operations().InsertOperation(fixExistOperation()) 502 assert.NoError(t, err) 503 err = memoryStorage.Instances().Insert(internal.Instance{ 504 InstanceID: instanceID, 505 GlobalAccountID: globalAccountID, 506 ServiceID: serviceID, 507 ServicePlanID: broker.TrialPlanID, 508 }) 509 assert.NoError(t, err) 510 511 queue := &automock.Queue{} 512 queue.On("Add", mock.AnythingOfType("string")) 513 514 factoryBuilder := &automock.PlanValidator{} 515 factoryBuilder.On("IsPlanSupport", broker.TrialPlanID).Return(true) 516 517 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 518 return &gqlschema.ClusterConfigInput{}, nil 519 } 520 provisionEndpoint := broker.NewProvision( 521 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite", broker.TrialPlanName}, OnlySingleTrialPerGA: false}, 522 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 523 memoryStorage.Operations(), 524 memoryStorage.Instances(), 525 queue, 526 factoryBuilder, 527 broker.PlansConfig{}, 528 false, 529 planDefaults, 530 euaccess.WhitelistSet{}, 531 "request rejected, your globalAccountId is not whitelisted", 532 logrus.StandardLogger(), 533 dashboardConfig, 534 ) 535 536 // when 537 response, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), otherInstanceID, domain.ProvisionDetails{ 538 ServiceID: serviceID, 539 PlanID: broker.TrialPlanID, 540 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 541 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, userID)), 542 }, true) 543 544 // then 545 require.NoError(t, err) 546 assert.Regexp(t, "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$", response.OperationData) 547 assert.NotEqual(t, instanceID, response.OperationData) 548 549 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 550 require.NoError(t, err) 551 assert.Equal(t, operation.InstanceID, otherInstanceID) 552 553 assert.Equal(t, globalAccountID, operation.ProvisioningParameters.ErsContext.GlobalAccountID) 554 assert.Equal(t, clusterName, operation.ProvisioningParameters.Parameters.Name) 555 assert.Equal(t, "req-region", operation.ProvisioningParameters.PlatformRegion) 556 557 instance, err := memoryStorage.Instances().GetByID(otherInstanceID) 558 require.NoError(t, err) 559 560 assert.Equal(t, instance.Parameters, operation.ProvisioningParameters) 561 assert.Equal(t, instance.GlobalAccountID, globalAccountID) 562 }) 563 564 t.Run("provision trial", func(t *testing.T) { 565 // given 566 memoryStorage := storage.NewMemoryStorage() 567 memoryStorage.Instances().Insert(internal.Instance{ 568 InstanceID: instanceID, 569 GlobalAccountID: "other-global-account", 570 ServiceID: serviceID, 571 ServicePlanID: broker.TrialPlanID, 572 }) 573 574 queue := &automock.Queue{} 575 queue.On("Add", mock.AnythingOfType("string")) 576 577 factoryBuilder := &automock.PlanValidator{} 578 factoryBuilder.On("IsPlanSupport", broker.TrialPlanID).Return(true) 579 580 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 581 return &gqlschema.ClusterConfigInput{}, nil 582 } 583 provisionEndpoint := broker.NewProvision( 584 broker.Config{EnablePlans: []string{"gcp", "azure", "trial"}, OnlySingleTrialPerGA: true}, 585 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 586 memoryStorage.Operations(), 587 memoryStorage.Instances(), 588 queue, 589 factoryBuilder, 590 broker.PlansConfig{}, 591 false, 592 planDefaults, 593 euaccess.WhitelistSet{}, 594 "request rejected, your globalAccountId is not whitelisted", 595 logrus.StandardLogger(), 596 dashboardConfig, 597 ) 598 599 // when 600 response, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 601 ServiceID: serviceID, 602 PlanID: broker.TrialPlanID, 603 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 604 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, userID)), 605 }, true) 606 607 // then 608 require.NoError(t, err) 609 assert.Regexp(t, "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$", response.OperationData) 610 assert.NotEqual(t, instanceID, response.OperationData) 611 612 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 613 require.NoError(t, err) 614 assert.Equal(t, operation.InstanceID, instanceID) 615 616 assert.Equal(t, globalAccountID, operation.ProvisioningParameters.ErsContext.GlobalAccountID) 617 assert.Equal(t, clusterName, operation.ProvisioningParameters.Parameters.Name) 618 assert.Equal(t, "req-region", operation.ProvisioningParameters.PlatformRegion) 619 620 instance, err := memoryStorage.Instances().GetByID(instanceID) 621 require.NoError(t, err) 622 623 assert.Equal(t, instance.Parameters, operation.ProvisioningParameters) 624 assert.Equal(t, instance.GlobalAccountID, globalAccountID) 625 }) 626 627 t.Run("fail if trial with invalid region", func(t *testing.T) { 628 // given 629 memoryStorage := storage.NewMemoryStorage() 630 memoryStorage.Instances().Insert(internal.Instance{ 631 InstanceID: instanceID, 632 GlobalAccountID: "other-global-account", 633 ServiceID: serviceID, 634 ServicePlanID: broker.TrialPlanID, 635 }) 636 637 queue := &automock.Queue{} 638 queue.On("Add", mock.AnythingOfType("string")) 639 640 factoryBuilder := &automock.PlanValidator{} 641 factoryBuilder.On("IsPlanSupport", broker.TrialPlanID).Return(true) 642 643 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 644 return &gqlschema.ClusterConfigInput{}, nil 645 } 646 provisionEndpoint := broker.NewProvision( 647 broker.Config{EnablePlans: []string{"gcp", "azure", "trial"}, OnlySingleTrialPerGA: true}, 648 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 649 memoryStorage.Operations(), 650 memoryStorage.Instances(), 651 queue, 652 factoryBuilder, 653 broker.PlansConfig{}, 654 false, 655 planDefaults, 656 euaccess.WhitelistSet{}, 657 "request rejected, your globalAccountId is not whitelisted", 658 logrus.StandardLogger(), 659 dashboardConfig, 660 ) 661 662 // when 663 _, err := provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 664 ServiceID: serviceID, 665 PlanID: broker.TrialPlanID, 666 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s", "region":"invalid-region"}`, clusterName)), 667 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, userID)), 668 }, true) 669 670 // then 671 require.ErrorContains(t, err, "invalid region specified in request for trial") 672 }) 673 674 t.Run("conflict should be handled", func(t *testing.T) { 675 // given 676 // #setup memory storage 677 memoryStorage := storage.NewMemoryStorage() 678 err := memoryStorage.Operations().InsertOperation(fixExistOperation()) 679 assert.NoError(t, err) 680 err = memoryStorage.Instances().Insert(fixInstance()) 681 assert.NoError(t, err) 682 683 factoryBuilder := &automock.PlanValidator{} 684 factoryBuilder.On("IsPlanSupport", planID).Return(true) 685 686 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 687 return &gqlschema.ClusterConfigInput{}, nil 688 } 689 // #create provisioner endpoint 690 provisionEndpoint := broker.NewProvision( 691 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite"}, OnlySingleTrialPerGA: true}, 692 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 693 memoryStorage.Operations(), 694 memoryStorage.Instances(), 695 nil, 696 factoryBuilder, 697 broker.PlansConfig{}, 698 false, 699 planDefaults, 700 euaccess.WhitelistSet{}, 701 "request rejected, your globalAccountId is not whitelisted", 702 logrus.StandardLogger(), 703 dashboardConfig, 704 ) 705 706 // when 707 response, err := provisionEndpoint.Provision(fixRequestContext(t, "dummy"), instanceID, domain.ProvisionDetails{ 708 ServiceID: serviceID, 709 PlanID: planID, 710 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 711 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, "1cafb9c8-c8f8-478a-948a-9cb53bb76aa4", subAccountID, userID)), 712 }, true) 713 714 // then 715 assert.EqualError(t, err, "provisioning operation already exist") 716 assert.Empty(t, response.OperationData) 717 }) 718 719 t.Run("kyma version parameters should be saved", func(t *testing.T) { 720 // given 721 memoryStorage := storage.NewMemoryStorage() 722 723 factoryBuilder := &automock.PlanValidator{} 724 factoryBuilder.On("IsPlanSupport", planID).Return(true) 725 726 queue := &automock.Queue{} 727 queue.On("Add", mock.AnythingOfType("string")) 728 729 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 730 return &gqlschema.ClusterConfigInput{}, nil 731 } 732 provisionEndpoint := broker.NewProvision( 733 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite"}, OnlySingleTrialPerGA: true}, 734 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 735 memoryStorage.Operations(), 736 memoryStorage.Instances(), 737 queue, 738 factoryBuilder, 739 broker.PlansConfig{}, 740 true, 741 planDefaults, 742 euaccess.WhitelistSet{}, 743 "request rejected, your globalAccountId is not whitelisted", 744 logrus.StandardLogger(), 745 dashboardConfig, 746 ) 747 748 // when 749 response, err := provisionEndpoint.Provision(fixRequestContext(t, "dummy"), instanceID, domain.ProvisionDetails{ 750 ServiceID: serviceID, 751 PlanID: planID, 752 RawParameters: json.RawMessage(fmt.Sprintf(`{ 753 "name": "%s", 754 "kymaVersion": "main-00e83e99" 755 }`, clusterName)), 756 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, "1cafb9c8-c8f8-478a-948a-9cb53bb76aa4", subAccountID, userID)), 757 }, true) 758 assert.NoError(t, err) 759 760 // then 761 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 762 require.NoError(t, err) 763 764 assert.Equal(t, "main-00e83e99", operation.ProvisioningParameters.Parameters.KymaVersion) 765 }) 766 767 t.Run("should return error when region is not specified", func(t *testing.T) { 768 // given 769 factoryBuilder := &automock.PlanValidator{} 770 factoryBuilder.On("IsPlanSupport", planID).Return(true) 771 772 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 773 return &gqlschema.ClusterConfigInput{}, nil 774 } 775 provisionEndpoint := broker.NewProvision( 776 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite"}, OnlySingleTrialPerGA: true}, 777 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 778 nil, 779 nil, 780 nil, 781 factoryBuilder, 782 broker.PlansConfig{}, 783 true, 784 planDefaults, 785 euaccess.WhitelistSet{}, 786 "request rejected, your globalAccountId is not whitelisted", 787 logrus.StandardLogger(), 788 dashboardConfig, 789 ) 790 791 // when 792 _, provisionErr := provisionEndpoint.Provision(context.Background(), instanceID, domain.ProvisionDetails{ 793 ServiceID: serviceID, 794 PlanID: planID, 795 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 796 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, "1cafb9c8-c8f8-478a-948a-9cb53bb76aa4", subAccountID, userID)), 797 }, true) 798 799 // then 800 require.EqualError(t, provisionErr, "No region specified in request.") 801 }) 802 803 t.Run("kyma version parameters should NOT be saved", func(t *testing.T) { 804 // given 805 memoryStorage := storage.NewMemoryStorage() 806 807 factoryBuilder := &automock.PlanValidator{} 808 factoryBuilder.On("IsPlanSupport", planID).Return(true) 809 810 queue := &automock.Queue{} 811 queue.On("Add", mock.AnythingOfType("string")) 812 813 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 814 return &gqlschema.ClusterConfigInput{}, nil 815 } 816 provisionEndpoint := broker.NewProvision( 817 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite"}, OnlySingleTrialPerGA: true}, 818 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 819 memoryStorage.Operations(), 820 memoryStorage.Instances(), 821 queue, 822 factoryBuilder, 823 broker.PlansConfig{}, 824 false, 825 planDefaults, 826 euaccess.WhitelistSet{}, 827 "request rejected, your globalAccountId is not whitelisted", 828 logrus.StandardLogger(), 829 dashboardConfig, 830 ) 831 832 // when 833 response, err := provisionEndpoint.Provision(fixRequestContext(t, "dummy"), instanceID, domain.ProvisionDetails{ 834 ServiceID: serviceID, 835 PlanID: planID, 836 RawParameters: json.RawMessage(fmt.Sprintf(`{ 837 "name": "%s", 838 "kymaVersion": "main-00e83e99" 839 }`, clusterName)), 840 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, "1cafb9c8-c8f8-478a-948a-9cb53bb76aa4", subAccountID, userID)), 841 }, true) 842 assert.NoError(t, err) 843 844 // then 845 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 846 require.NoError(t, err) 847 848 assert.Equal(t, "", operation.ProvisioningParameters.Parameters.KymaVersion) 849 }) 850 851 t.Run("licence type lite should be saved in parameters", func(t *testing.T) { 852 // given 853 memoryStorage := storage.NewMemoryStorage() 854 855 factoryBuilder := &automock.PlanValidator{} 856 factoryBuilder.On("IsPlanSupport", broker.AzureLitePlanID).Return(true) 857 858 queue := &automock.Queue{} 859 queue.On("Add", mock.AnythingOfType("string")) 860 861 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 862 return &gqlschema.ClusterConfigInput{}, nil 863 } 864 provisionEndpoint := broker.NewProvision( 865 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite"}, OnlySingleTrialPerGA: true}, 866 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 867 memoryStorage.Operations(), 868 memoryStorage.Instances(), 869 queue, 870 factoryBuilder, 871 broker.PlansConfig{}, 872 false, 873 planDefaults, 874 euaccess.WhitelistSet{}, 875 "request rejected, your globalAccountId is not whitelisted", 876 logrus.StandardLogger(), 877 dashboardConfig, 878 ) 879 880 // when 881 response, err := provisionEndpoint.Provision(fixRequestContext(t, "dummy"), instanceID, domain.ProvisionDetails{ 882 ServiceID: serviceID, 883 PlanID: broker.AzureLitePlanID, 884 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 885 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, "1cafb9c8-c8f8-478a-948a-9cb53bb76aa4", subAccountID, userID)), 886 }, true) 887 assert.NoError(t, err) 888 889 // then 890 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 891 require.NoError(t, err) 892 893 assert.Equal(t, ptr.String(internal.LicenceTypeLite), operation.ProvisioningParameters.Parameters.LicenceType) 894 }) 895 896 t.Run("licence type lite should be saved in parameters for Trial Plan", func(t *testing.T) { 897 // given 898 memoryStorage := storage.NewMemoryStorage() 899 900 factoryBuilder := &automock.PlanValidator{} 901 factoryBuilder.On("IsPlanSupport", broker.TrialPlanID).Return(true) 902 903 queue := &automock.Queue{} 904 queue.On("Add", mock.AnythingOfType("string")) 905 906 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 907 return &gqlschema.ClusterConfigInput{}, nil 908 } 909 provisionEndpoint := broker.NewProvision( 910 broker.Config{EnablePlans: []string{"gcp", "azure", "azure_lite", "trial"}, OnlySingleTrialPerGA: true}, 911 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 912 memoryStorage.Operations(), 913 memoryStorage.Instances(), 914 queue, 915 factoryBuilder, 916 broker.PlansConfig{}, 917 false, 918 planDefaults, 919 euaccess.WhitelistSet{}, 920 "request rejected, your globalAccountId is not whitelisted", 921 logrus.StandardLogger(), 922 dashboardConfig, 923 ) 924 925 // when 926 response, err := provisionEndpoint.Provision(fixRequestContext(t, "dummy"), instanceID, domain.ProvisionDetails{ 927 ServiceID: serviceID, 928 PlanID: broker.TrialPlanID, 929 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s"}`, clusterName)), 930 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, "1cafb9c8-c8f8-478a-948a-9cb53bb76aa4", subAccountID, userID)), 931 }, true) 932 assert.NoError(t, err) 933 934 // then 935 operation, err := memoryStorage.Operations().GetProvisioningOperationByID(response.OperationData) 936 require.NoError(t, err) 937 938 assert.Equal(t, ptr.String(internal.LicenceTypeLite), operation.ProvisioningParameters.Parameters.LicenceType) 939 }) 940 941 t.Run("Should fail on insufficient OIDC params (missing issuerURL)", func(t *testing.T) { 942 // given 943 memoryStorage := storage.NewMemoryStorage() 944 945 queue := &automock.Queue{} 946 queue.On("Add", mock.AnythingOfType("string")) 947 948 factoryBuilder := &automock.PlanValidator{} 949 factoryBuilder.On("IsPlanSupport", planID).Return(true) 950 951 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 952 return &gqlschema.ClusterConfigInput{}, nil 953 } 954 // #create provisioner endpoint 955 provisionEndpoint := broker.NewProvision( 956 broker.Config{ 957 EnablePlans: []string{"gcp", "azure"}, 958 URL: brokerURL, 959 OnlySingleTrialPerGA: true, 960 EnableKubeconfigURLLabel: true, 961 }, 962 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 963 memoryStorage.Operations(), 964 memoryStorage.Instances(), 965 queue, 966 factoryBuilder, 967 broker.PlansConfig{}, 968 false, 969 planDefaults, 970 euaccess.WhitelistSet{}, 971 "request rejected, your globalAccountId is not whitelisted", 972 logrus.StandardLogger(), 973 dashboardConfig, 974 ) 975 976 oidcParams := `"clientID":"client-id"` 977 err := fmt.Errorf("issuerURL must not be empty") 978 errMsg := fmt.Sprintf("[instanceID: %s] %s", instanceID, err) 979 expectedErr := apiresponses.NewFailureResponse(err, http.StatusBadRequest, errMsg) 980 981 // when 982 _, err = provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 983 ServiceID: serviceID, 984 PlanID: planID, 985 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s","oidc":{ %s }}`, clusterName, oidcParams)), 986 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 987 }, true) 988 t.Logf("%+v\n", *provisionEndpoint) 989 990 // then 991 require.Error(t, err) 992 assert.IsType(t, &apiresponses.FailureResponse{}, err) 993 apierr := err.(*apiresponses.FailureResponse) 994 assert.Equal(t, expectedErr.ValidatedStatusCode(nil), apierr.ValidatedStatusCode(nil)) 995 assert.Equal(t, expectedErr.LoggerAction(), apierr.LoggerAction()) 996 }) 997 998 t.Run("Should fail on insufficient OIDC params (missing clientID)", func(t *testing.T) { 999 // given 1000 memoryStorage := storage.NewMemoryStorage() 1001 1002 queue := &automock.Queue{} 1003 queue.On("Add", mock.AnythingOfType("string")) 1004 1005 factoryBuilder := &automock.PlanValidator{} 1006 factoryBuilder.On("IsPlanSupport", planID).Return(true) 1007 1008 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 1009 return &gqlschema.ClusterConfigInput{}, nil 1010 } 1011 // #create provisioner endpoint 1012 provisionEndpoint := broker.NewProvision( 1013 broker.Config{ 1014 EnablePlans: []string{"gcp", "azure"}, 1015 URL: brokerURL, 1016 OnlySingleTrialPerGA: true, 1017 EnableKubeconfigURLLabel: true, 1018 }, 1019 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 1020 memoryStorage.Operations(), 1021 memoryStorage.Instances(), 1022 queue, 1023 factoryBuilder, 1024 broker.PlansConfig{}, 1025 false, 1026 planDefaults, 1027 euaccess.WhitelistSet{}, 1028 "request rejected, your globalAccountId is not whitelisted", 1029 logrus.StandardLogger(), 1030 dashboardConfig, 1031 ) 1032 1033 oidcParams := `"issuerURL":"https://test.local"` 1034 err := fmt.Errorf("clientID must not be empty") 1035 errMsg := fmt.Sprintf("[instanceID: %s] %s", instanceID, err) 1036 expectedErr := apiresponses.NewFailureResponse(err, http.StatusBadRequest, errMsg) 1037 1038 // when 1039 _, err = provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 1040 ServiceID: serviceID, 1041 PlanID: planID, 1042 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s","oidc":{ %s }}`, clusterName, oidcParams)), 1043 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 1044 }, true) 1045 t.Logf("%+v\n", *provisionEndpoint) 1046 1047 // then 1048 require.Error(t, err) 1049 assert.IsType(t, &apiresponses.FailureResponse{}, err) 1050 apierr := err.(*apiresponses.FailureResponse) 1051 assert.Equal(t, expectedErr.ValidatedStatusCode(nil), apierr.ValidatedStatusCode(nil)) 1052 assert.Equal(t, expectedErr.LoggerAction(), apierr.LoggerAction()) 1053 }) 1054 1055 t.Run("Should fail on invalid OIDC signingAlgs param", func(t *testing.T) { 1056 // given 1057 memoryStorage := storage.NewMemoryStorage() 1058 1059 queue := &automock.Queue{} 1060 queue.On("Add", mock.AnythingOfType("string")) 1061 1062 factoryBuilder := &automock.PlanValidator{} 1063 factoryBuilder.On("IsPlanSupport", planID).Return(true) 1064 1065 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 1066 return &gqlschema.ClusterConfigInput{}, nil 1067 } 1068 // #create provisioner endpoint 1069 provisionEndpoint := broker.NewProvision( 1070 broker.Config{ 1071 EnablePlans: []string{"gcp", "azure"}, 1072 URL: brokerURL, 1073 OnlySingleTrialPerGA: true, 1074 EnableKubeconfigURLLabel: true, 1075 }, 1076 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 1077 memoryStorage.Operations(), 1078 memoryStorage.Instances(), 1079 queue, 1080 factoryBuilder, 1081 broker.PlansConfig{}, 1082 false, 1083 planDefaults, 1084 euaccess.WhitelistSet{}, 1085 "request rejected, your globalAccountId is not whitelisted", 1086 logrus.StandardLogger(), 1087 dashboardConfig, 1088 ) 1089 1090 oidcParams := `"clientID":"client-id","issuerURL":"https://test.local","signingAlgs":["RS256","notValid"]` 1091 err := fmt.Errorf("signingAlgs must contain valid signing algorithm(s)") 1092 errMsg := fmt.Sprintf("[instanceID: %s] %s", instanceID, err) 1093 expectedErr := apiresponses.NewFailureResponse(err, http.StatusBadRequest, errMsg) 1094 1095 // when 1096 _, err = provisionEndpoint.Provision(fixRequestContext(t, "req-region"), instanceID, domain.ProvisionDetails{ 1097 ServiceID: serviceID, 1098 PlanID: planID, 1099 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s","oidc":{ %s }}`, clusterName, oidcParams)), 1100 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 1101 }, true) 1102 t.Logf("%+v\n", *provisionEndpoint) 1103 1104 // then 1105 require.Error(t, err) 1106 assert.IsType(t, &apiresponses.FailureResponse{}, err) 1107 apierr := err.(*apiresponses.FailureResponse) 1108 assert.Equal(t, expectedErr.ValidatedStatusCode(nil), apierr.ValidatedStatusCode(nil)) 1109 assert.Equal(t, expectedErr.LoggerAction(), apierr.LoggerAction()) 1110 }) 1111 1112 t.Run("Should pass for whitelisted globalAccountId - EU Access", func(t *testing.T) { 1113 // given 1114 memoryStorage := storage.NewMemoryStorage() 1115 1116 queue := &automock.Queue{} 1117 queue.On("Add", mock.AnythingOfType("string")) 1118 1119 factoryBuilder := &automock.PlanValidator{} 1120 factoryBuilder.On("IsPlanSupport", planID).Return(true) 1121 1122 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 1123 return &gqlschema.ClusterConfigInput{}, nil 1124 } 1125 // #create provisioner endpoint 1126 provisionEndpoint := broker.NewProvision( 1127 broker.Config{ 1128 EnablePlans: []string{"gcp", "azure"}, 1129 URL: brokerURL, 1130 OnlySingleTrialPerGA: true, 1131 EnableKubeconfigURLLabel: true, 1132 }, 1133 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 1134 memoryStorage.Operations(), 1135 memoryStorage.Instances(), 1136 queue, 1137 factoryBuilder, 1138 broker.PlansConfig{}, 1139 false, 1140 planDefaults, 1141 euaccess.WhitelistSet{whitelistedGlobalAccountID: struct{}{}}, 1142 "request rejected, your globalAccountId is not whitelisted", 1143 logrus.StandardLogger(), 1144 dashboardConfig, 1145 ) 1146 1147 oidcParams := `"clientID":"client-id","issuerURL":"https://test.local","signingAlgs":["RS256"]` 1148 1149 // when 1150 _, err := provisionEndpoint.Provision(fixRequestContext(t, "cf-eu11"), instanceID, domain.ProvisionDetails{ 1151 ServiceID: serviceID, 1152 PlanID: planID, 1153 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s","oidc":{ %s }}`, clusterName, oidcParams)), 1154 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, whitelistedGlobalAccountID, subAccountID, "Test@Test.pl")), 1155 }, true) 1156 t.Logf("%+v\n", *provisionEndpoint) 1157 1158 // then 1159 require.NoError(t, err) 1160 }) 1161 1162 t.Run("Should fail for not whitelisted globalAccountId - EU Access", func(t *testing.T) { 1163 // given 1164 memoryStorage := storage.NewMemoryStorage() 1165 1166 queue := &automock.Queue{} 1167 queue.On("Add", mock.AnythingOfType("string")) 1168 1169 factoryBuilder := &automock.PlanValidator{} 1170 factoryBuilder.On("IsPlanSupport", planID).Return(true) 1171 1172 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 1173 return &gqlschema.ClusterConfigInput{}, nil 1174 } 1175 // #create provisioner endpoint 1176 provisionEndpoint := broker.NewProvision( 1177 broker.Config{ 1178 EnablePlans: []string{"gcp", "azure"}, 1179 URL: brokerURL, 1180 OnlySingleTrialPerGA: true, 1181 EnableKubeconfigURLLabel: true, 1182 }, 1183 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 1184 memoryStorage.Operations(), 1185 memoryStorage.Instances(), 1186 queue, 1187 factoryBuilder, 1188 broker.PlansConfig{}, 1189 false, 1190 planDefaults, 1191 euaccess.WhitelistSet{}, 1192 "request rejected, your globalAccountId is not whitelisted", 1193 logrus.StandardLogger(), 1194 dashboardConfig, 1195 ) 1196 1197 oidcParams := `"clientID":"client-id","issuerURL":"https://test.local","signingAlgs":["RS256"]` 1198 err := fmt.Errorf("request rejected, your globalAccountId is not whitelisted") 1199 errMsg := fmt.Sprintf("[instanceID: %s] %s", instanceID, err) 1200 expectedErr := apiresponses.NewFailureResponse(err, http.StatusBadRequest, errMsg) 1201 1202 // when 1203 _, err = provisionEndpoint.Provision(fixRequestContext(t, "cf-eu11"), instanceID, domain.ProvisionDetails{ 1204 ServiceID: serviceID, 1205 PlanID: planID, 1206 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "%s","oidc":{ %s }}`, clusterName, oidcParams)), 1207 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, "Test@Test.pl")), 1208 }, true) 1209 t.Logf("%+v\n", *provisionEndpoint) 1210 1211 // then 1212 require.Error(t, err) 1213 assert.IsType(t, &apiresponses.FailureResponse{}, err) 1214 apierr := err.(*apiresponses.FailureResponse) 1215 assert.Equal(t, expectedErr.ValidatedStatusCode(nil), apierr.ValidatedStatusCode(nil)) 1216 assert.Equal(t, expectedErr.LoggerAction(), apierr.LoggerAction()) 1217 }) 1218 } 1219 1220 func TestNetworkingValidation(t *testing.T) { 1221 for tn, tc := range map[string]struct { 1222 givenNetworking string 1223 1224 expectedError bool 1225 }{ 1226 "Invalid nodes CIDR": { 1227 givenNetworking: `{"nodes": 1abcd"}`, 1228 expectedError: true, 1229 }, 1230 "Invalid nodes CIDR - wrong IP range": { 1231 givenNetworking: `{"nodes": "10.250.0.1/22"}`, 1232 expectedError: true, 1233 }, 1234 "Valid CIDRs": { 1235 givenNetworking: `{"nodes": "10.250.0.0/20"}`, 1236 expectedError: false, 1237 }, 1238 "Overlaps with seed cidr": { 1239 givenNetworking: `{"nodes": "10.243.128.0/18"}`, 1240 expectedError: true, 1241 }, 1242 /*"Invalid pods CIDR": { 1243 givenNetworking: `{"nodes": "10.250.0.0/16", "pods": "10abcd/16", "services": "100.104.0.0/13"}`, 1244 expectedError: true, 1245 }, 1246 "Invalid pods CIDR - wrong IP range": { 1247 givenNetworking: `{"nodes": "10.250.0.0/16", "pods": "10.250.0.1/19", "services": "100.104.0.0/13"}`, 1248 expectedError: true, 1249 }, 1250 "Invalid services CIDR": { 1251 givenNetworking: `{"nodes": "10.250.0.0/16", "pods": "10.250.0.1/19", "services": "abcd"}`, 1252 expectedError: true, 1253 }, 1254 "Invalid services CIDR - wrong IP range": { 1255 givenNetworking: `{"nodes": "10.250.0.0/16", "pods": "10.250.0.1/19", "services": "10.250.0.1/19"}`, 1256 expectedError: true, 1257 }, 1258 "Pods and Services overlaps": { 1259 givenNetworking: `{"nodes": "10.250.0.0/22", "pods": "10.64.0.0/19", "services": "10.64.0.0/16"}`, 1260 expectedError: true, 1261 },*/ 1262 "Pods and Nodes overlaps": { 1263 givenNetworking: `{"nodes": "10.96.0.0/16"}`, 1264 expectedError: true, 1265 }, 1266 "Services and Nodes overlaps": { 1267 givenNetworking: `{"nodes": "10.104.0.0/13"}`, 1268 expectedError: true, 1269 }, 1270 "Suffix too big": { 1271 givenNetworking: `{"nodes": "10.250.0.0/25"}`, 1272 expectedError: true, 1273 }, 1274 } { 1275 t.Run(tn, func(t *testing.T) { 1276 // given 1277 // #setup memory storage 1278 memoryStorage := storage.NewMemoryStorage() 1279 1280 queue := &automock.Queue{} 1281 queue.On("Add", mock.AnythingOfType("string")) 1282 1283 factoryBuilder := &automock.PlanValidator{} 1284 factoryBuilder.On("IsPlanSupport", mock.AnythingOfType("string")).Return(true) 1285 1286 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 1287 return &gqlschema.ClusterConfigInput{}, nil 1288 } 1289 // #create provisioner endpoint 1290 provisionEndpoint := broker.NewProvision( 1291 broker.Config{EnablePlans: []string{"gcp", "azure", "free"}, AllowNetworkingParameters: true}, 1292 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 1293 memoryStorage.Operations(), 1294 memoryStorage.Instances(), 1295 queue, 1296 factoryBuilder, 1297 broker.PlansConfig{}, 1298 false, 1299 planDefaults, 1300 euaccess.WhitelistSet{}, 1301 "request rejected, your globalAccountId is not whitelisted", 1302 logrus.StandardLogger(), 1303 dashboardConfig, 1304 ) 1305 1306 // when 1307 _, err := provisionEndpoint.Provision(fixRequestContextWithProvider(t, "cf-eu10", "azure"), instanceID, 1308 domain.ProvisionDetails{ 1309 ServiceID: serviceID, 1310 PlanID: broker.AzurePlanID, 1311 RawParameters: json.RawMessage(fmt.Sprintf(`{"name": "cluster-name", "networking": %s}`, tc.givenNetworking)), 1312 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, userID)), 1313 }, true) 1314 1315 // then 1316 assert.Equal(t, tc.expectedError, err != nil) 1317 }) 1318 } 1319 1320 } 1321 1322 func TestRegionValidation(t *testing.T) { 1323 1324 for tn, tc := range map[string]struct { 1325 planID string 1326 parameters string 1327 platformProvider internal.CloudProvider 1328 1329 expectedErrorStatusCode int 1330 expectedError bool 1331 }{ 1332 "invalid region": { 1333 planID: broker.AzurePlanID, 1334 platformProvider: internal.Azure, 1335 parameters: `{"name": "cluster-name", "region":"not-valid"}`, 1336 1337 expectedErrorStatusCode: http.StatusBadRequest, 1338 expectedError: true, 1339 }, 1340 "Azure region for AWS freemium": { 1341 planID: broker.FreemiumPlanID, 1342 platformProvider: internal.AWS, 1343 parameters: `{"name": "cluster-name", "region": "eastus"}`, 1344 1345 expectedErrorStatusCode: http.StatusBadRequest, 1346 expectedError: true, 1347 }, 1348 "Azure region for Azure freemium": { 1349 planID: broker.FreemiumPlanID, 1350 platformProvider: internal.Azure, 1351 parameters: `{"name": "cluster-name", "region": "eastus"}`, 1352 1353 expectedError: false, 1354 }, 1355 "AWS region for AWS freemium": { 1356 planID: broker.FreemiumPlanID, 1357 platformProvider: internal.AWS, 1358 parameters: `{"name": "cluster-name", "region": "eu-central-1"}`, 1359 1360 expectedError: false, 1361 }, 1362 "AWS region for Azure freemium": { 1363 planID: broker.FreemiumPlanID, 1364 platformProvider: internal.Azure, 1365 parameters: `{"name": "cluster-name", "region": "eu-central-1"}`, 1366 1367 expectedErrorStatusCode: http.StatusBadRequest, 1368 expectedError: true, 1369 }, 1370 } { 1371 t.Run(tn, func(t *testing.T) { 1372 // given 1373 // #setup memory storage 1374 memoryStorage := storage.NewMemoryStorage() 1375 1376 queue := &automock.Queue{} 1377 queue.On("Add", mock.AnythingOfType("string")) 1378 1379 factoryBuilder := &automock.PlanValidator{} 1380 factoryBuilder.On("IsPlanSupport", tc.planID).Return(true) 1381 1382 planDefaults := func(planID string, platformProvider internal.CloudProvider, provider *internal.CloudProvider) (*gqlschema.ClusterConfigInput, error) { 1383 return &gqlschema.ClusterConfigInput{}, nil 1384 } 1385 // #create provisioner endpoint 1386 provisionEndpoint := broker.NewProvision( 1387 broker.Config{EnablePlans: []string{"gcp", "azure", "free"}, OnlySingleTrialPerGA: true}, 1388 gardener.Config{Project: "test", ShootDomain: "example.com", DNSProviders: fixDNSProviders()}, 1389 memoryStorage.Operations(), 1390 memoryStorage.Instances(), 1391 queue, 1392 factoryBuilder, 1393 broker.PlansConfig{}, 1394 false, 1395 planDefaults, 1396 euaccess.WhitelistSet{}, 1397 "request rejected, your globalAccountId is not whitelisted", 1398 logrus.StandardLogger(), 1399 dashboardConfig, 1400 ) 1401 1402 // when 1403 _, err := provisionEndpoint.Provision(fixRequestContextWithProvider(t, "cf-eu10", tc.platformProvider), instanceID, 1404 domain.ProvisionDetails{ 1405 ServiceID: serviceID, 1406 PlanID: tc.planID, 1407 RawParameters: json.RawMessage(tc.parameters), 1408 RawContext: json.RawMessage(fmt.Sprintf(`{"globalaccount_id": "%s", "subaccount_id": "%s", "user_id": "%s"}`, globalAccountID, subAccountID, userID)), 1409 }, true) 1410 1411 // then 1412 if tc.expectedError { 1413 require.Error(t, err) 1414 assert.Equal(t, tc.expectedErrorStatusCode, err.(*apiresponses.FailureResponse).ValidatedStatusCode(nil)) 1415 } else { 1416 assert.NoError(t, err) 1417 } 1418 1419 }) 1420 } 1421 1422 } 1423 1424 func fixExistOperation() internal.Operation { 1425 provisioningOperation := fixture.FixProvisioningOperation(existOperationID, instanceID) 1426 provisioningOperation.ProvisioningParameters = internal.ProvisioningParameters{ 1427 PlanID: planID, 1428 ServiceID: serviceID, 1429 ErsContext: internal.ERSContext{ 1430 SubAccountID: subAccountID, 1431 GlobalAccountID: globalAccountID, 1432 UserID: userID, 1433 }, 1434 Parameters: internal.ProvisioningParametersDTO{ 1435 Name: clusterName, 1436 }, 1437 PlatformRegion: region, 1438 } 1439 1440 return provisioningOperation 1441 } 1442 1443 func fixInstance() internal.Instance { 1444 return fixture.FixInstance(instanceID) 1445 } 1446 1447 func fixRequestContext(t *testing.T, region string) context.Context { 1448 t.Helper() 1449 return fixRequestContextWithProvider(t, region, internal.Azure) 1450 } 1451 1452 func fixRequestContextWithProvider(t *testing.T, region string, provider internal.CloudProvider) context.Context { 1453 t.Helper() 1454 1455 ctx := context.TODO() 1456 ctx = middleware.AddRegionToCtx(ctx, region) 1457 ctx = middleware.AddProviderToCtx(ctx, provider) 1458 return ctx 1459 } 1460 1461 func fixDNSProviders() gardener.DNSProvidersData { 1462 return gardener.DNSProvidersData{ 1463 Providers: []gardener.DNSProviderData{ 1464 { 1465 DomainsInclude: []string{"dev.example.com"}, 1466 Primary: true, 1467 SecretName: "aws_dns_domain_secrets_test_instance", 1468 Type: "route53_type_test", 1469 }, 1470 }, 1471 } 1472 }