Repository: chef/automate
Pull request #8222 (2023-09-13 09:09:19)

validation fix
### :nut_and_bolt: Description: What code changed, and why?

<!-- /!\ Please ensure that you are NOT disclosing any customer information without their consent /!\ -->

### :chains: Related Resources
https://chefio.atlassian.net/browse/CHEF-6367

### :+1: Definition of Done

### :athletic_shoe: How to Build and Test the Change

### :white_check_mark: Checklist

**All PRs** must tick these:

- [ ] I have read the [CONTRIBUTING document](https://github.com/chef/automate/blob/master/CONTRIBUTING.md).
- [ ] All commits signed-off for the [Developer Certification of Origin](https://github.com/chef/chef/blob/master/CONTRIBUTING.md#developer-certification-of-origin-dco).

With occasional exceptions, all PRs **from Progress employees** must tick these:

- [ ] Is the code clear? *(complicated code or lots of comments--subdivide and use well-named methods, meaningful variable names, etc.)*
- [ ] Consistency checked? *(user notifications, user prompts, visual patterns, code patterns, variable names)*
- [ ] Repeated code blocks eliminated? *(adapt and reuse existing components, blocks, functions, etc.)*
- [ ] Spelling, grammar, typos checked? *(at a minimum use `make spell` in any component directory)*
- [ ] Code well-formatted? *(indents, line breaks, etc. improve rather than hinder readability)*

All PRs **from Progress employees** should tick these if appropriate:

- [ ] Tests added/updated? (all new code needs new tests)
- [ ] Docs added/updated? (all customer-facing changes)

*Please add a note next to any checkbox above if you are NOT ticking it.*

### :camera: Screenshots, if applicable
<img width="831" alt="Screenshot 2023-09-13 at 2 42 30 PM" src="https://github.com/chef/automate/assets/98326242/cf68e85f-aadb-4ef1-9df1-47b630f6b595">


sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222) [![B](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/B-16px.png 'B')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222) Maintainability Rating on New Code (is worse than A)  

[See analysis details on SonarQube](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222)

Fix issues before they fail your Quality Gate with [![SonarLint](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/sonarlint-16px.png 'SonarLint')](https://www.sonarqube.org/sonarlint/?referrer=pull-request) [SonarLint in your IDE](https://www.sonarqube.org/sonarlint/?referrer=pull-request).
sonarqube-for-infrastructure-prod[bot]: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonar.progress.com/dashboard?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/bug-16px.png 'Bug')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=BUG) [0 Bugs](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/vulnerability-16px.png 'Vulnerability')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/security_hotspot-16px.png 'Security Hotspot')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222) [0 Security Hotspots](https://sonar.progress.com/security_hotspots?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/common/code_smell-16px.png 'Code Smell')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/RatingBadge/A-16px.png 'A')](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonar.progress.com/project/issues?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&resolved=false&types=CODE_SMELL)

[![100.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/CoverageChart/100-16px.png '100.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&metric=new_coverage&view=list) [100.0% Coverage](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/Duplications/3-16px.png '0.0%')](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonar.progress.com/component_measures?id=chef_automate_AYeOVEbqJ4YHsO5MtKWC&pullRequest=8222&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/lib/config/hadeployconfigverify.go b/lib/config/hadeployconfigverify.go
index 9f248f8be..67eee5024 100644
--- a/lib/config/hadeployconfigverify.go
+++ b/lib/config/hadeployconfigverify.go
@@ -175,6 +175,13 @@ func (c *HaDeployConfig) validateAwsBackupConfig() error {
 
 func (c *HaDeployConfig) verifyObjectStorage(objectStorage *ConfigObjectStorage) error {
 	errorList := list.New()
+
+	if c.IsExternalDb() {
+		if err := validateRequiredString(objectStorage.Location, "location", "s3"); err != nil {
+			return err
+		}
+	}
+
 	if err := validateRequiredString(objectStorage.BucketName, "bucket_name"); err != nil {
 		errorList.PushBack(err)
 	}
@@ -184,20 +191,9 @@ func (c *HaDeployConfig) verifyObjectStorage(objectStorage *ConfigObjectStorage)
 		}
 	}
 	if objectStorage.Location == AWS_S3 {
-		if err := validateRequiredString(objectStorage.AccessKey, "access_key"); err != nil {
+		if err := verifyS3(objectStorage); err != nil {
 			errorList.PushBack(err)
 		}
-		if err := validateRequiredString(objectStorage.SecretKey, "secret_key"); err != nil {
-			errorList.PushBack(err)
-		}
-		if err := validateS3Endpoint(objectStorage.Endpoint); err != nil {
-			errorList.PushBack(err)
-		}
-		if objectStorage.Region != "" {
-			if err := validateS3AWSRegion(objectStorage.Region); err != nil {
-				errorList.PushBack(err)
-			}
-		}
 	}
 	return getSingleErrorFromList(errorList)
 }
@@ -723,3 +719,22 @@ func awsChefSettings(aws *ConfigAwsSettings) error {
 
 	return getSingleErrorFromList(errorList)
 }
+
+func verifyS3(objectStorage *ConfigObjectStorage) error {
+	errorList := list.New()
+	if err := validateRequiredString(objectStorage.AccessKey, "access_key"); err != nil {
+		errorList.PushBack(err)
+	}
+	if err := validateRequiredString(objectStorage.SecretKey, "secret_key"); err != nil {
+		errorList.PushBack(err)
+	}
+	if err := validateS3Endpoint(objectStorage.Endpoint); err != nil {
+		errorList.PushBack(err)
+	}
+	if objectStorage.Region != "" {
+		if err := validateS3AWSRegion(objectStorage.Region); err != nil {
+			errorList.PushBack(err)
+		}
+	}
+	return getSingleErrorFromList(errorList)
+}


Test patch:
diff --git a/lib/config/hadeployconfigverify_test.go b/lib/config/hadeployconfigverify_test.go
index bec93d180..1d9a6d0dd 100644
--- a/lib/config/hadeployconfigverify_test.go
+++ b/lib/config/hadeployconfigverify_test.go
@@ -120,9 +120,10 @@ func TestParseAndVerify(t *testing.T) {
 
 func TestVerifyObjectStorage(t *testing.T) {
 	testCases := []struct {
-		name          string
-		objectStorage *ConfigObjectStorage
-		expectedError error
+		name           string
+		objectStorage  *ConfigObjectStorage
+		haDeployConfig *HaDeployConfig
+		expectedError  error
 	}{
 		{
 			name: "Valid Object Storage Configuration",
@@ -134,7 +135,8 @@ func TestVerifyObjectStorage(t *testing.T) {
 				Endpoint:   "https://example.com",
 				Region:     "us-east-1",
 			},
-			expectedError: nil,
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  nil,
 		},
 		{
 			name: "Missing Bucket Name",
@@ -145,7 +147,8 @@ func TestVerifyObjectStorage(t *testing.T) {
 				Endpoint:  "https://example.com",
 				Region:    "us-east-1",
 			},
-			expectedError: errors.New("invalid or empty: bucket_name"),
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  errors.New("invalid or empty: bucket_name"),
 		},
 		{
 			name: "Missing Access Key",
@@ -156,7 +159,8 @@ func TestVerifyObjectStorage(t *testing.T) {
 				Endpoint:   "https://example.com",
 				Region:     "us-east-1",
 			},
-			expectedError: errors.New("invalid or empty: access_key"),
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  errors.New("invalid or empty: access_key"),
 		},
 		{
 			name: "Missing Secret Key",
@@ -167,7 +171,8 @@ func TestVerifyObjectStorage(t *testing.T) {
 				Endpoint:   "https://example.com",
 				Region:     "us-east-1",
 			},
-			expectedError: errors.New("invalid or empty: secret_key"),
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  errors.New("invalid or empty: secret_key"),
 		},
 		{
 			name: "Missing Endpoint",
@@ -178,7 +183,8 @@ func TestVerifyObjectStorage(t *testing.T) {
 				SecretKey:  "secret-key",
 				Region:     "us-east-1",
 			},
-			expectedError: errors.New("invalid or empty: endpoint"),
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  errors.New("invalid or empty: endpoint"),
 		},
 		{
 			name: "Invalid Region",
@@ -190,7 +196,8 @@ func TestVerifyObjectStorage(t *testing.T) {
 				Endpoint:   "https://example.com",
 				Region:     "invalid-region",
 			},
-			expectedError: errors.New("invalid AWS region for S3"),
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  errors.New("invalid AWS region for S3"),
 		},
 		{
 			name: "Empty Bucket",
@@ -198,7 +205,8 @@ func TestVerifyObjectStorage(t *testing.T) {
 				Location:                 GCS_STORAGE,
 				GoogleServiceAccountFile: "./testdata/gcsservicefile.json",
 			},
-			expectedError: errors.New("invalid or empty: bucket_name"),
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  errors.New("invalid or empty: bucket_name"),
 		},
 		{
 			name: "Empty ServiceFile",
@@ -207,13 +215,30 @@ func TestVerifyObjectStorage(t *testing.T) {
 				BucketName:               "bucket",
 				GoogleServiceAccountFile: "./testdata/servicefile.json",
 			},
-			expectedError: errors.New("invalid google_service_account_file: ./testdata/servicefile.json no such file or directory"),
+			haDeployConfig: &HaDeployConfig{},
+			expectedError:  errors.New("invalid google_service_account_file: ./testdata/servicefile.json no such file or directory"),
+		},
+		{
+			name: "Error For haDeployConfigDatabase",
+			objectStorage: &ConfigObjectStorage{
+				Location:                 GCS_STORAGE,
+				BucketName:               "bucket",
+				GoogleServiceAccountFile: "./testdata/servicefile.json",
+			},
+			haDeployConfig: &HaDeployConfig{
+				External: &ExternalSettings{
+					Database: &ExternalDBSettings{
+						Type: "aws",
+					},
+				},
+			},
+			expectedError: errors.New("invalid value 'gcs' for field 'location'. Expected values are: s3"),
 		},
 	}
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			c := &HaDeployConfig{} // Initialize HaDeployConfig instance
-			err := c.verifyObjectStorage(tc.objectStorage)
+			// Initialize HaDeployConfig instance
+			err := tc.haDeployConfig.verifyObjectStorage(tc.objectStorage)
 			if err != nil && tc.expectedError != nil {
 				assert.EqualErrorf(t, err, tc.expectedError.Error(), "")
 			}