github.com/jenkins-x/jx/v2@v2.1.155/pkg/config/install_requirements_test.go (about) 1 // +build unit 2 3 package config_test 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path" 10 "path/filepath" 11 "testing" 12 13 "github.com/jenkins-x/jx/v2/pkg/cloud/gke" 14 "github.com/stretchr/testify/require" 15 16 "github.com/ghodss/yaml" 17 "github.com/jenkins-x/jx-logging/pkg/log" 18 "github.com/jenkins-x/jx/v2/pkg/cloud" 19 "github.com/jenkins-x/jx/v2/pkg/config" 20 "github.com/jenkins-x/jx/v2/pkg/gits" 21 "github.com/jenkins-x/jx/v2/pkg/util" 22 "github.com/stretchr/testify/assert" 23 ) 24 25 var ( 26 testDataDir = path.Join("test_data") 27 ) 28 29 func TestRequirementsConfigMarshalExistingFile(t *testing.T) { 30 t.Parallel() 31 32 dir, err := ioutil.TempDir("", "test-requirements-config-") 33 assert.NoError(t, err, "should create a temporary config dir") 34 35 expectedClusterName := "my-cluster" 36 expectedSecretStorage := config.SecretStorageTypeVault 37 expectedDomain := "cheese.co.uk" 38 39 file := filepath.Join(dir, config.RequirementsConfigFileName) 40 requirements := config.NewRequirementsConfig() 41 requirements.SecretStorage = expectedSecretStorage 42 requirements.Cluster.ClusterName = expectedClusterName 43 requirements.Ingress.Domain = expectedDomain 44 requirements.Kaniko = true 45 46 err = requirements.SaveConfig(file) 47 assert.NoError(t, err, "failed to save file %s", file) 48 49 requirements, fileName, err := config.LoadRequirementsConfig(dir, config.DefaultFailOnValidationError) 50 assert.NoError(t, err, "failed to load requirements file in dir %s", dir) 51 assert.FileExists(t, fileName) 52 53 assert.Equal(t, true, requirements.Kaniko, "requirements.Kaniko") 54 assert.Equal(t, expectedClusterName, requirements.Cluster.ClusterName, "requirements.ClusterName") 55 assert.Equal(t, expectedSecretStorage, requirements.SecretStorage, "requirements.SecretStorage") 56 assert.Equal(t, expectedDomain, requirements.Ingress.Domain, "requirements.Domain") 57 58 // lets check we can load the file from a sub dir 59 subDir := filepath.Join(dir, "subdir") 60 requirements, fileName, err = config.LoadRequirementsConfig(subDir, config.DefaultFailOnValidationError) 61 assert.NoError(t, err, "failed to load requirements file in subDir: %s", subDir) 62 assert.FileExists(t, fileName) 63 64 assert.Equal(t, true, requirements.Kaniko, "requirements.Kaniko") 65 assert.Equal(t, expectedClusterName, requirements.Cluster.ClusterName, "requirements.ClusterName") 66 assert.Equal(t, expectedSecretStorage, requirements.SecretStorage, "requirements.SecretStorage") 67 assert.Equal(t, expectedDomain, requirements.Ingress.Domain, "requirements.Domain") 68 } 69 70 func Test_OverrideRequirementsFromEnvironment_does_not_initialise_nil_structs(t *testing.T) { 71 requirements, fileName, err := config.LoadRequirementsConfig(testDataDir, config.DefaultFailOnValidationError) 72 assert.NoError(t, err, "failed to load requirements file in dir %s", testDataDir) 73 assert.FileExists(t, fileName) 74 75 requirements.OverrideRequirementsFromEnvironment(func() gke.GClouder { 76 return nil 77 }) 78 79 tempDir, err := ioutil.TempDir("", "test-requirements-config") 80 assert.NoError(t, err, "should create a temporary config dir") 81 defer func() { 82 _ = os.RemoveAll(tempDir) 83 }() 84 85 err = requirements.SaveConfig(filepath.Join(tempDir, config.RequirementsConfigFileName)) 86 assert.NoError(t, err, "failed to save requirements file in dir %s", tempDir) 87 88 overrideRequirements, fileName, err := config.LoadRequirementsConfig(tempDir, config.DefaultFailOnValidationError) 89 assert.NoError(t, err, "failed to load requirements file in dir %s", testDataDir) 90 assert.FileExists(t, fileName) 91 92 assert.Nil(t, overrideRequirements.BuildPacks, "nil values should not be populated") 93 } 94 95 func Test_OverrideRequirementsFromEnvironment_populate_requirements_from_environment_variables(t *testing.T) { 96 var overrideTests = []struct { 97 envKey string 98 envValue string 99 expectedRequirements config.RequirementsConfig 100 }{ 101 // RequirementsConfig 102 {config.RequirementSecretStorageType, "vault", config.RequirementsConfig{SecretStorage: "vault"}}, 103 {config.RequirementKaniko, "true", config.RequirementsConfig{Kaniko: true}}, 104 {config.RequirementKaniko, "false", config.RequirementsConfig{Kaniko: false}}, 105 {config.RequirementKaniko, "", config.RequirementsConfig{Kaniko: false}}, 106 {config.RequirementRepository, "bucketrepo", config.RequirementsConfig{Repository: "bucketrepo"}}, 107 {config.RequirementWebhook, "prow", config.RequirementsConfig{Webhook: "prow"}}, 108 {config.RequirementGitAppEnabled, "true", config.RequirementsConfig{GithubApp: &config.GithubAppConfig{Enabled: true}}}, 109 {config.RequirementGitAppEnabled, "false", config.RequirementsConfig{GithubApp: &config.GithubAppConfig{Enabled: false}}}, 110 {config.RequirementGitAppURL, "https://my-github-app", config.RequirementsConfig{GithubApp: &config.GithubAppConfig{URL: "https://my-github-app"}}}, 111 112 // ClusterConfig 113 {config.RequirementClusterName, "my-cluster", config.RequirementsConfig{Cluster: config.ClusterConfig{ClusterName: "my-cluster"}}}, 114 {config.RequirementProject, "my-project", config.RequirementsConfig{Cluster: config.ClusterConfig{ProjectID: "my-project"}}}, 115 {config.RequirementZone, "my-zone", config.RequirementsConfig{Cluster: config.ClusterConfig{Zone: "my-zone"}}}, 116 {config.RequirementChartRepository, "my-chart-museum", config.RequirementsConfig{Cluster: config.ClusterConfig{ChartRepository: "my-chart-museum"}}}, 117 {config.RequirementRegistry, "my-registry", config.RequirementsConfig{Cluster: config.ClusterConfig{Registry: "my-registry"}}}, 118 {config.RequirementEnvGitOwner, "john-doe", config.RequirementsConfig{Cluster: config.ClusterConfig{EnvironmentGitOwner: "john-doe"}}}, 119 {config.RequirementKanikoServiceAccountName, "kaniko-sa", config.RequirementsConfig{Cluster: config.ClusterConfig{KanikoSAName: "kaniko-sa"}}}, 120 {config.RequirementEnvGitPublic, "true", config.RequirementsConfig{Cluster: config.ClusterConfig{EnvironmentGitPublic: true}}}, 121 {config.RequirementEnvGitPublic, "false", config.RequirementsConfig{Cluster: config.ClusterConfig{EnvironmentGitPublic: false}}}, 122 {config.RequirementEnvGitPublic, "", config.RequirementsConfig{Cluster: config.ClusterConfig{EnvironmentGitPublic: false}}}, 123 {config.RequirementGitPublic, "true", config.RequirementsConfig{Cluster: config.ClusterConfig{GitPublic: true}}}, 124 {config.RequirementGitPublic, "false", config.RequirementsConfig{Cluster: config.ClusterConfig{GitPublic: false}}}, 125 {config.RequirementGitPublic, "", config.RequirementsConfig{Cluster: config.ClusterConfig{GitPublic: false}}}, 126 {config.RequirementExternalDNSServiceAccountName, "externaldns-sa", config.RequirementsConfig{Cluster: config.ClusterConfig{ExternalDNSSAName: "externaldns-sa"}}}, 127 128 // VaultConfig 129 {config.RequirementVaultName, "my-vault", config.RequirementsConfig{Vault: config.VaultConfig{Name: "my-vault"}}}, 130 {config.RequirementVaultServiceAccountName, "my-vault-sa", config.RequirementsConfig{Vault: config.VaultConfig{ServiceAccount: "my-vault-sa"}}}, 131 {config.RequirementVaultKeyringName, "my-keyring", config.RequirementsConfig{Vault: config.VaultConfig{Keyring: "my-keyring"}}}, 132 {config.RequirementVaultKeyName, "my-key", config.RequirementsConfig{Vault: config.VaultConfig{Key: "my-key"}}}, 133 {config.RequirementVaultBucketName, "my-bucket", config.RequirementsConfig{Vault: config.VaultConfig{Bucket: "my-bucket"}}}, 134 {config.RequirementVaultRecreateBucket, "true", config.RequirementsConfig{Vault: config.VaultConfig{RecreateBucket: true}}}, 135 {config.RequirementVaultRecreateBucket, "false", config.RequirementsConfig{Vault: config.VaultConfig{RecreateBucket: false}}}, 136 {config.RequirementVaultRecreateBucket, "", config.RequirementsConfig{Vault: config.VaultConfig{RecreateBucket: false}}}, 137 {config.RequirementVaultDisableURLDiscovery, "true", config.RequirementsConfig{Vault: config.VaultConfig{DisableURLDiscovery: true}}}, 138 {config.RequirementVaultDisableURLDiscovery, "false", config.RequirementsConfig{Vault: config.VaultConfig{DisableURLDiscovery: false}}}, 139 {config.RequirementVaultDisableURLDiscovery, "", config.RequirementsConfig{Vault: config.VaultConfig{DisableURLDiscovery: false}}}, 140 141 // VeleroConfig 142 {config.RequirementVeleroServiceAccountName, "my-velero-sa", config.RequirementsConfig{Velero: config.VeleroConfig{ServiceAccount: "my-velero-sa"}}}, 143 {config.RequirementVeleroTTL, "60", config.RequirementsConfig{Velero: config.VeleroConfig{TimeToLive: "60"}}}, 144 {config.RequirementVeleroSchedule, "0 * * * *", config.RequirementsConfig{Velero: config.VeleroConfig{Schedule: "0 * * * *"}}}, 145 146 // IngressConfig 147 {config.RequirementDomainIssuerURL, "my-issuer-url", config.RequirementsConfig{Ingress: config.IngressConfig{DomainIssuerURL: "my-issuer-url"}}}, 148 149 // Storage 150 {config.RequirementStorageBackupEnabled, "true", config.RequirementsConfig{Storage: config.StorageConfig{Backup: config.StorageEntryConfig{Enabled: true}}}}, 151 {config.RequirementStorageBackupEnabled, "false", config.RequirementsConfig{Storage: config.StorageConfig{Backup: config.StorageEntryConfig{Enabled: false}}}}, 152 {config.RequirementStorageBackupEnabled, "", config.RequirementsConfig{Storage: config.StorageConfig{Backup: config.StorageEntryConfig{Enabled: false}}}}, 153 {config.RequirementStorageBackupURL, "gs://my-backup", config.RequirementsConfig{Storage: config.StorageConfig{Backup: config.StorageEntryConfig{URL: "gs://my-backup"}}}}, 154 155 {config.RequirementStorageLogsEnabled, "true", config.RequirementsConfig{Storage: config.StorageConfig{Logs: config.StorageEntryConfig{Enabled: true}}}}, 156 {config.RequirementStorageLogsEnabled, "false", config.RequirementsConfig{Storage: config.StorageConfig{Logs: config.StorageEntryConfig{Enabled: false}}}}, 157 {config.RequirementStorageLogsEnabled, "", config.RequirementsConfig{Storage: config.StorageConfig{Logs: config.StorageEntryConfig{Enabled: false}}}}, 158 {config.RequirementStorageLogsURL, "gs://my-logs", config.RequirementsConfig{Storage: config.StorageConfig{Logs: config.StorageEntryConfig{URL: "gs://my-logs"}}}}, 159 160 {config.RequirementStorageReportsEnabled, "true", config.RequirementsConfig{Storage: config.StorageConfig{Reports: config.StorageEntryConfig{Enabled: true}}}}, 161 {config.RequirementStorageReportsEnabled, "false", config.RequirementsConfig{Storage: config.StorageConfig{Reports: config.StorageEntryConfig{Enabled: false}}}}, 162 {config.RequirementStorageReportsEnabled, "", config.RequirementsConfig{Storage: config.StorageConfig{Reports: config.StorageEntryConfig{Enabled: false}}}}, 163 {config.RequirementStorageReportsURL, "gs://my-reports", config.RequirementsConfig{Storage: config.StorageConfig{Reports: config.StorageEntryConfig{URL: "gs://my-reports"}}}}, 164 165 {config.RequirementStorageRepositoryEnabled, "true", config.RequirementsConfig{Storage: config.StorageConfig{Repository: config.StorageEntryConfig{Enabled: true}}}}, 166 {config.RequirementStorageRepositoryEnabled, "false", config.RequirementsConfig{Storage: config.StorageConfig{Repository: config.StorageEntryConfig{Enabled: false}}}}, 167 {config.RequirementStorageRepositoryEnabled, "", config.RequirementsConfig{Storage: config.StorageConfig{Repository: config.StorageEntryConfig{Enabled: false}}}}, 168 {config.RequirementStorageRepositoryURL, "gs://my-repo", config.RequirementsConfig{Storage: config.StorageConfig{Repository: config.StorageEntryConfig{URL: "gs://my-repo"}}}}, 169 170 // GKEConfig 171 {config.RequirementGkeProjectNumber, "my-gke-project", config.RequirementsConfig{Cluster: config.ClusterConfig{GKEConfig: &config.GKEConfig{ProjectNumber: "my-gke-project"}}}}, 172 173 // VersionStreamConfig 174 {config.RequirementVersionsGitRef, "v1.0.0", config.RequirementsConfig{VersionStream: config.VersionStreamConfig{Ref: "v1.0.0"}}}, 175 } 176 177 for _, overrideTest := range overrideTests { 178 origEnvValue, origValueSet := os.LookupEnv(overrideTest.envKey) 179 err := os.Setenv(overrideTest.envKey, overrideTest.envValue) 180 assert.NoError(t, err) 181 resetEnvVariable := func() { 182 var err error 183 if origValueSet { 184 err = os.Setenv(overrideTest.envKey, origEnvValue) 185 } else { 186 err = os.Unsetenv(overrideTest.envKey) 187 } 188 if err != nil { 189 log.Logger().Warnf("error resetting environment after test: %v", err) 190 } 191 } 192 193 t.Run(overrideTest.envKey, func(t *testing.T) { 194 actualRequirements := config.RequirementsConfig{} 195 actualRequirements.OverrideRequirementsFromEnvironment(func() gke.GClouder { 196 return nil 197 }) 198 199 assert.Equal(t, overrideTest.expectedRequirements, actualRequirements) 200 }) 201 202 resetEnvVariable() 203 } 204 } 205 206 func TestRequirementsConfigMarshalExistingFileKanikoFalse(t *testing.T) { 207 t.Parallel() 208 209 dir, err := ioutil.TempDir("", "test-requirements-config-") 210 assert.NoError(t, err, "should create a temporary config dir") 211 212 file := filepath.Join(dir, config.RequirementsConfigFileName) 213 requirements := config.NewRequirementsConfig() 214 requirements.Kaniko = false 215 216 err = requirements.SaveConfig(file) 217 assert.NoError(t, err, "failed to save file %s", file) 218 219 requirements, fileName, err := config.LoadRequirementsConfig(dir, config.DefaultFailOnValidationError) 220 assert.NoError(t, err, "failed to load requirements file in dir %s", dir) 221 assert.FileExists(t, fileName) 222 223 assert.Equal(t, false, requirements.Kaniko, "requirements.Kaniko") 224 225 } 226 227 func TestRequirementsConfigMarshalInEmptyDir(t *testing.T) { 228 t.Parallel() 229 230 dir, err := ioutil.TempDir("", "test-requirements-config-empty-") 231 232 requirements, fileName, err := config.LoadRequirementsConfig(dir, config.DefaultFailOnValidationError) 233 assert.Error(t, err) 234 assert.Empty(t, fileName) 235 assert.Nil(t, requirements) 236 } 237 238 func TestRequirementsConfigIngressAutoDNS(t *testing.T) { 239 t.Parallel() 240 241 requirements := config.NewRequirementsConfig() 242 243 requirements.Ingress.Domain = "1.2.3.4.nip.io" 244 assert.Equal(t, true, requirements.Ingress.IsAutoDNSDomain(), "requirements.Ingress.IsAutoDNSDomain() for domain %s", requirements.Ingress.Domain) 245 246 requirements.Ingress.Domain = "foo.bar" 247 assert.Equal(t, false, requirements.Ingress.IsAutoDNSDomain(), "requirements.Ingress.IsAutoDNSDomain() for domain %s", requirements.Ingress.Domain) 248 249 requirements.Ingress.Domain = "" 250 assert.Equal(t, false, requirements.Ingress.IsAutoDNSDomain(), "requirements.Ingress.IsAutoDNSDomain() for domain %s", requirements.Ingress.Domain) 251 } 252 253 func Test_unmarshalling_requirements_config_with_build_pack_configuration_succeeds(t *testing.T) { 254 t.Parallel() 255 256 requirements := config.NewRequirementsConfig() 257 258 content, err := ioutil.ReadFile(path.Join(testDataDir, "build_pack_library.yaml")) 259 260 err = yaml.Unmarshal(content, requirements) 261 assert.NoError(t, err) 262 assert.Equal(t, "Test name", requirements.BuildPacks.BuildPackLibrary.Name, "requirements.buildPacks.BuildPackLibrary.name is not equivalent to test name") 263 assert.Equal(t, "github.com", requirements.BuildPacks.BuildPackLibrary.GitURL, "requirements.buildPacks.BuildPackLibrary.gitURL is not equivalent to git url ") 264 assert.Equal(t, "master", requirements.BuildPacks.BuildPackLibrary.GitRef, "requirements.buildPacks.BuildPackLibrary.gitRef is not equivalent git Ref") 265 } 266 267 func Test_marshalling_empty_requirements_config_creates_no_build_pack_configuration(t *testing.T) { 268 t.Parallel() 269 270 requirements := config.NewRequirementsConfig() 271 data, err := yaml.Marshal(requirements) 272 assert.NoError(t, err) 273 assert.NotContains(t, string(data), "buildPacks") 274 275 err = yaml.Unmarshal(data, requirements) 276 assert.NoError(t, err) 277 assert.Nil(t, requirements.BuildPacks) 278 } 279 280 func Test_marshalling_vault_config(t *testing.T) { 281 t.Parallel() 282 283 requirements := config.NewRequirementsConfig() 284 requirements.Vault = config.VaultConfig{ 285 Name: "myVault", 286 URL: "http://myvault", 287 ServiceAccount: "vault-sa", 288 Namespace: "jx", 289 KubernetesAuthPath: "kubernetes", 290 SecretEngineMountPoint: "secret", 291 } 292 data, err := yaml.Marshal(requirements) 293 assert.NoError(t, err) 294 295 assert.Contains(t, string(data), "name: myVault") 296 assert.Contains(t, string(data), "url: http://myvault") 297 assert.Contains(t, string(data), "serviceAccount: vault-sa") 298 assert.Contains(t, string(data), "namespace: jx") 299 assert.Contains(t, string(data), "kubernetesAuthPath: kubernetes") 300 assert.Contains(t, string(data), "secretEngineMountPoint: secret") 301 } 302 303 func Test_env_repository_visibility(t *testing.T) { 304 t.Parallel() 305 306 var gitPublicTests = []struct { 307 yamlFile string 308 expectedGitPublic bool 309 }{ 310 {"git_public_nil_git_private_true.yaml", false}, 311 {"git_public_nil_git_private_false.yaml", true}, 312 {"git_public_false_git_private_nil.yaml", false}, 313 {"git_public_true_git_private_nil.yaml", true}, 314 } 315 316 for _, testCase := range gitPublicTests { 317 t.Run(testCase.yamlFile, func(t *testing.T) { 318 content, err := ioutil.ReadFile(path.Join(testDataDir, testCase.yamlFile)) 319 assert.NoError(t, err) 320 321 config := config.NewRequirementsConfig() 322 323 _ = log.CaptureOutput(func() { 324 err = yaml.Unmarshal(content, config) 325 assert.NoError(t, err) 326 assert.Equal(t, testCase.expectedGitPublic, config.Cluster.EnvironmentGitPublic, "unexpected value for repository visibility") 327 }) 328 }) 329 } 330 } 331 332 func TestMergeSave(t *testing.T) { 333 t.Parallel() 334 type TestSpec struct { 335 Name string 336 Original *config.RequirementsConfig 337 Changed *config.RequirementsConfig 338 ValidationFunc func(orig *config.RequirementsConfig, ch *config.RequirementsConfig) 339 } 340 341 testCases := []TestSpec{ 342 { 343 Name: "Merge Cluster Config Test", 344 Original: &config.RequirementsConfig{ 345 Cluster: config.ClusterConfig{ 346 EnvironmentGitOwner: "owner", 347 EnvironmentGitPublic: false, 348 GitPublic: false, 349 Provider: cloud.GKE, 350 Namespace: "jx", 351 ProjectID: "project-id", 352 ClusterName: "cluster-name", 353 Region: "region", 354 GitKind: gits.KindGitHub, 355 GitServer: gits.KindGitHub, 356 }, 357 }, 358 Changed: &config.RequirementsConfig{ 359 Cluster: config.ClusterConfig{ 360 EnvironmentGitPublic: true, 361 GitPublic: true, 362 Provider: cloud.GKE, 363 }, 364 }, 365 ValidationFunc: func(orig *config.RequirementsConfig, ch *config.RequirementsConfig) { 366 assert.True(t, orig.Cluster.EnvironmentGitPublic == ch.Cluster.EnvironmentGitPublic && 367 orig.Cluster.GitPublic == ch.Cluster.GitPublic && 368 orig.Cluster.ProjectID != ch.Cluster.ProjectID, "ClusterConfig validation failed") 369 }, 370 }, 371 { 372 Name: "Merge EnvironmentConfig slices Test", 373 Original: &config.RequirementsConfig{ 374 Environments: []config.EnvironmentConfig{ 375 { 376 Key: "dev", 377 Repository: "repo", 378 }, 379 { 380 Key: "production", 381 Ingress: config.IngressConfig{ 382 Domain: "domain", 383 }, 384 }, 385 { 386 Key: "staging", 387 Ingress: config.IngressConfig{ 388 Domain: "domainStaging", 389 TLS: config.TLSConfig{ 390 Email: "email", 391 }, 392 }, 393 }, 394 }, 395 }, 396 Changed: &config.RequirementsConfig{ 397 Environments: []config.EnvironmentConfig{ 398 { 399 Key: "dev", 400 Owner: "owner", 401 }, 402 { 403 Key: "production", 404 Ingress: config.IngressConfig{ 405 CloudDNSSecretName: "secret", 406 }, 407 }, 408 { 409 Key: "staging", 410 Ingress: config.IngressConfig{ 411 Domain: "newDomain", 412 DomainIssuerURL: "issuer", 413 TLS: config.TLSConfig{ 414 Enabled: true, 415 }, 416 }, 417 }, 418 { 419 Key: "ns2", 420 }, 421 }, 422 }, 423 ValidationFunc: func(orig *config.RequirementsConfig, ch *config.RequirementsConfig) { 424 assert.True(t, len(orig.Environments) == len(ch.Environments), "the environment slices should be of the same len") 425 // -- Dev Environment's asserts 426 devOrig, devCh := orig.Environments[0], ch.Environments[0] 427 assert.True(t, devOrig.Owner == devCh.Owner && devOrig.Repository != devCh.Repository, 428 "the dev environment should've been merged correctly") 429 // -- Production Environment's asserts 430 prOrig, prCh := orig.Environments[1], ch.Environments[1] 431 assert.True(t, prOrig.Ingress.Domain == "domain" && 432 prOrig.Ingress.CloudDNSSecretName == prCh.Ingress.CloudDNSSecretName, 433 "the production environment should've been merged correctly") 434 // -- Staging Environmnet's asserts 435 stgOrig, stgCh := orig.Environments[2], ch.Environments[2] 436 assert.True(t, stgOrig.Ingress.Domain == stgCh.Ingress.Domain && 437 stgOrig.Ingress.TLS.Email == "email" && stgOrig.Ingress.TLS.Enabled == stgCh.Ingress.TLS.Enabled, 438 "the staging environment should've been merged correctly") 439 }, 440 }, 441 { 442 Name: "Merge StorageConfig test", 443 Original: &config.RequirementsConfig{ 444 Storage: config.StorageConfig{ 445 Logs: config.StorageEntryConfig{ 446 Enabled: true, 447 URL: "value1", 448 }, 449 Reports: config.StorageEntryConfig{}, 450 Repository: config.StorageEntryConfig{ 451 Enabled: true, 452 URL: "value3", 453 }, 454 }, 455 }, 456 Changed: &config.RequirementsConfig{ 457 Storage: config.StorageConfig{ 458 Reports: config.StorageEntryConfig{ 459 Enabled: true, 460 URL: "", 461 }, 462 }, 463 }, 464 ValidationFunc: func(orig *config.RequirementsConfig, ch *config.RequirementsConfig) { 465 assert.True(t, orig.Storage.Logs.Enabled && orig.Storage.Logs.URL == "value1" && 466 orig.Storage.Repository.Enabled && orig.Storage.Repository.URL == "value3" && 467 orig.Storage.Reports.Enabled == ch.Storage.Reports.Enabled, 468 "The storage configuration should've been merged correctly") 469 }, 470 }, 471 } 472 f, err := ioutil.TempFile("", "") 473 assert.NoError(t, err) 474 defer util.DeleteFile(f.Name()) 475 476 for _, tc := range testCases { 477 t.Run(tc.Name, func(t *testing.T) { 478 err = tc.Original.MergeSave(tc.Changed, f.Name()) 479 assert.NoError(t, err, "the merge shouldn't fail for case %s", tc.Name) 480 tc.ValidationFunc(tc.Original, tc.Changed) 481 }) 482 } 483 } 484 485 func Test_EnvironmentGitPublic_and_EnvironmentGitPrivate_specified_together_return_error(t *testing.T) { 486 content, err := ioutil.ReadFile(path.Join(testDataDir, "git_public_true_git_private_true.yaml")) 487 assert.NoError(t, err) 488 489 config := config.NewRequirementsConfig() 490 err = yaml.Unmarshal(content, config) 491 assert.Error(t, err) 492 assert.Contains(t, err.Error(), "only EnvironmentGitPublic should be used") 493 } 494 495 func TestHelmfileRequirementValues(t *testing.T) { 496 t.Parallel() 497 498 dir, err := ioutil.TempDir("", "test-requirements-config-") 499 assert.NoError(t, err, "should create a temporary config dir") 500 501 file := filepath.Join(dir, config.RequirementsConfigFileName) 502 requirements := config.NewRequirementsConfig() 503 requirements.Cluster.ClusterName = "jx_rocks" 504 505 err = requirements.SaveConfig(file) 506 assert.NoError(t, err, "failed to save file %s", file) 507 assert.FileExists(t, file) 508 valuesFile := filepath.Join(dir, config.RequirementsValuesFileName) 509 510 valuesFileExists, err := util.FileExists(valuesFile) 511 assert.False(t, valuesFileExists, "file %s should not exist", valuesFile) 512 513 requirements.Helmfile = true 514 err = requirements.SaveConfig(file) 515 assert.NoError(t, err, "failed to save file %s", file) 516 assert.FileExists(t, file) 517 assert.FileExists(t, valuesFile, "file %s should exist", valuesFile) 518 } 519 520 func Test_LoadRequirementsConfig(t *testing.T) { 521 t.Parallel() 522 523 var gitPublicTests = []struct { 524 requirementsPath string 525 createRequirements bool 526 }{ 527 {"a", false}, 528 {"a/b", false}, 529 {"a/b/c", false}, 530 {"e", true}, 531 {"e/f", true}, 532 {"e/f/g", true}, 533 } 534 535 for _, testCase := range gitPublicTests { 536 t.Run(testCase.requirementsPath, func(t *testing.T) { 537 dir, err := ioutil.TempDir("", "jx-test-load-requirements-config") 538 require.NoError(t, err, "failed to create tmp directory") 539 defer func() { 540 _ = os.RemoveAll(dir) 541 }() 542 543 testPath := filepath.Join(dir, testCase.requirementsPath) 544 err = os.MkdirAll(testPath, 0700) 545 require.NoError(t, err, "unable to create test path %s", testPath) 546 547 var expectedRequirementsFile string 548 if testCase.createRequirements { 549 expectedRequirementsFile = filepath.Join(testPath, config.RequirementsConfigFileName) 550 dummyRequirementsData := []byte("webhook: prow\n") 551 err := ioutil.WriteFile(expectedRequirementsFile, dummyRequirementsData, 0600) 552 require.NoError(t, err, "unable to write requirements file %s", expectedRequirementsFile) 553 } 554 555 requirements, requirementsFile, err := config.LoadRequirementsConfig(testPath, config.DefaultFailOnValidationError) 556 if testCase.createRequirements { 557 require.NoError(t, err) 558 assert.Equal(t, expectedRequirementsFile, requirementsFile) 559 assert.Equal(t, fmt.Sprintf("%s", requirements.Webhook), "prow") 560 } else { 561 require.Error(t, err) 562 assert.Equal(t, "", requirementsFile) 563 assert.Nil(t, requirements) 564 } 565 }) 566 } 567 } 568 569 func TestLoadRequirementsConfig_load_invalid_yaml(t *testing.T) { 570 testDir := path.Join(testDataDir, "jx-requirements-syntax-error") 571 572 absolute, err := filepath.Abs(testDir) 573 assert.NoError(t, err, "could not find absolute path of dir %s", testDataDir) 574 575 _, _, err = config.LoadRequirementsConfig(testDir, config.DefaultFailOnValidationError) 576 requirementsConfigPath := path.Join(absolute, config.RequirementsConfigFileName) 577 assert.EqualError(t, err, fmt.Sprintf("validation failures in YAML file %s:\nenvironments.0: Additional property namespace is not allowed", requirementsConfigPath)) 578 }