-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #581 from itsmitul9/osd-23280
OSD-23280 Osdctl configuration setup
- Loading branch information
Showing
3 changed files
with
326 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package setup | ||
|
||
import ( | ||
"bufio" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"regexp" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
const ( | ||
ProdJumproleConfigKey = "prod_jumprole_account_id" | ||
AwsProxy = "aws_proxy" | ||
StageJumproleConfigKey = "stage_jumprole_account_id" | ||
PdUserToken = "pd_user_token" | ||
JiraToken = "jira_token" | ||
DtVaultPath = "dt_vault_path" | ||
VaultAddress = "vault_address" | ||
CloudTrailCmdLists = "cloudtrail_cmd_lists" | ||
JiraTokenRegex = "^[A-Z0-9]{7}$" | ||
PdTokenRegex = "^[a-zA-Z0-9+_-]{20}$" | ||
AwsAccountRegex = "^[0-9]{12}$" | ||
AWSProxyRegex = `^http:\/\/[a-zA-Z0-9.-]+(:\d+)?$` | ||
VaultURLRegex = `^https:\/\/[a-zA-Z0-9.-]+\/?$` | ||
DtVaultPathRegex = `^[a-zA-Z0-9\-/]+$` | ||
CloudTrailCmdListsRegex = `^\s*-\s+.*$` | ||
) | ||
|
||
// NewCmdSetup implements the setup command | ||
func NewCmdSetup() *cobra.Command { | ||
setupCmd := &cobra.Command{ | ||
Use: "setup", | ||
Short: "Setup the configuration", | ||
Args: cobra.NoArgs, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
keys := []string{ | ||
ProdJumproleConfigKey, | ||
AwsProxy, | ||
StageJumproleConfigKey, | ||
} | ||
|
||
optionalKeys := []string{ | ||
DtVaultPath, | ||
VaultAddress, | ||
PdUserToken, | ||
JiraToken, | ||
CloudTrailCmdLists, | ||
} | ||
|
||
values := make(map[string]string) | ||
reader := bufio.NewReader(os.Stdin) | ||
|
||
defaults := make(map[string]string) | ||
for _, key := range keys { | ||
defaultValue := viper.GetString(key) | ||
defaults[key] = defaultValue | ||
} | ||
|
||
for _, key := range optionalKeys { | ||
defaultValue := viper.GetString(key) | ||
defaults[key] = defaultValue | ||
} | ||
|
||
for _, key := range keys { | ||
defaultValue := defaults[key] | ||
fmt.Printf("\033[91mEnter %s \033[0m [\033[94mdefault %s\033[0m]:", key, defaultValue) | ||
value, _ := reader.ReadString('\n') | ||
value = strings.TrimSpace(value) | ||
|
||
if value == "" { | ||
value = defaultValue | ||
} | ||
|
||
var err error | ||
switch key { | ||
case JiraToken: | ||
if value != "" && value != defaultValue { | ||
_, err = ValidateJiraToken(value) | ||
} | ||
case PdUserToken: | ||
if value != "" && value != defaultValue { | ||
_, err = ValidatePDToken(value) | ||
} | ||
case ProdJumproleConfigKey, StageJumproleConfigKey: | ||
if value != "" && value != defaultValue { | ||
_, err = ValidateAWSAccount(value) | ||
} | ||
case AwsProxy: | ||
if value != "" && value != defaultValue { | ||
_, err = ValidateAWSProxy(value) | ||
} | ||
case VaultAddress: | ||
if value != "" && value != defaultValue { | ||
_, err = ValidateVaultAddress(value) | ||
} | ||
case DtVaultPath: | ||
if value != "" && value != defaultValue { | ||
_, err = ValidateDtVaultPath(value) | ||
} | ||
case CloudTrailCmdLists: | ||
if value != "" && value != defaultValue { | ||
_, err = ValidateCloudTrailCmdLists(value) | ||
} | ||
} | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
values[key] = value | ||
} | ||
|
||
for _, key := range optionalKeys { | ||
defaultValue := defaults[key] | ||
fmt.Printf("\033[91mEnter %s (optional)\033[0m [\033[94mdefault %s\033[0m]:", key, defaultValue) | ||
value, _ := reader.ReadString('\n') | ||
value = strings.TrimSpace(value) | ||
|
||
if value == "" { | ||
value = defaultValue | ||
} | ||
|
||
if value != "" && value != defaultValue { | ||
values[key] = value | ||
} | ||
} | ||
|
||
// Store the value in the config file | ||
for key, value := range values { | ||
viper.Set(key, value) | ||
} | ||
err := viper.WriteConfig() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Println("Configuration saved successfully") | ||
return nil | ||
}, | ||
} | ||
return setupCmd | ||
} | ||
|
||
func ValidateJiraToken(token string) (string, error) { | ||
token = strings.TrimSpace(token) | ||
match, err := regexp.MatchString(JiraTokenRegex, token) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !match { | ||
return "", errors.New("invalid jira token") | ||
} | ||
return token, nil | ||
} | ||
|
||
func ValidatePDToken(token string) (string, error) { | ||
token = strings.TrimSpace(token) | ||
match, err := regexp.MatchString(PdTokenRegex, token) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !match { | ||
return "", errors.New("invalid pd token") | ||
} | ||
return token, nil | ||
} | ||
|
||
func ValidateAWSAccount(account string) (string, error) { | ||
account = strings.TrimSpace(account) | ||
match, err := regexp.MatchString(AwsAccountRegex, account) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !match { | ||
return "", errors.New("invalid AWS account number") | ||
} | ||
return account, nil | ||
} | ||
|
||
func ValidateAWSProxy(proxyURL string) (string, error) { | ||
proxyURL = strings.TrimSpace(proxyURL) | ||
match, err := regexp.MatchString(AWSProxyRegex, proxyURL) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !match { | ||
return "", errors.New("invalid AWS proxy URL") | ||
} | ||
return proxyURL, nil | ||
} | ||
|
||
func ValidateVaultAddress(vaultURL string) (string, error) { | ||
vaultURL = strings.TrimSpace(vaultURL) | ||
match, err := regexp.MatchString(VaultURLRegex, vaultURL) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !match { | ||
return "", errors.New("invalid Vault URL") | ||
} | ||
return vaultURL, nil | ||
} | ||
|
||
func ValidateDtVaultPath(dtVaultPath string) (string, error) { | ||
dtVaultPath = strings.TrimSpace(dtVaultPath) | ||
match, err := regexp.MatchString(DtVaultPathRegex, dtVaultPath) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !match { | ||
return "", errors.New("invalid DtVault Path") | ||
} | ||
return dtVaultPath, nil | ||
} | ||
|
||
func ValidateCloudTrailCmdLists(cloudTrailCmd string) (string, error) { | ||
cloudTrailCmd = strings.TrimSpace(cloudTrailCmd) | ||
match, err := regexp.MatchString(CloudTrailCmdListsRegex, cloudTrailCmd) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !match { | ||
return "", errors.New("invalid CloudTrail command") | ||
} | ||
return cloudTrailCmd, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package setup | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestSetup(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Setup Suite") | ||
} | ||
|
||
var _ = Describe("Validation Functions", func() { | ||
Context("Jira Token", func() { | ||
It("should validate correct Jira token", func() { | ||
token, _ := ValidateJiraToken("ABC1234") | ||
//Expect(err).To(BeNil()) | ||
Expect(token).To(Equal("ABC1234")) | ||
}) | ||
|
||
It("should fail invalid Jira token", func() { | ||
_, err := ValidateJiraToken("invalid") // this should fail since "INVALID" does not match ^[A-Z0-9]{7}$ | ||
Expect(err).To(HaveOccurred()) | ||
}) | ||
}) | ||
|
||
Context("PD Token", func() { | ||
It("should validate correct PD token", func() { | ||
token, err := ValidatePDToken("abcdEFGHijklMNOPqrst") | ||
Expect(err).To(BeNil()) | ||
Expect(token).To(Equal("abcdEFGHijklMNOPqrst")) | ||
}) | ||
|
||
It("should fail invalid PD token", func() { | ||
_, err := ValidatePDToken("short") // this should fail since "short" does not match ^[a-zA-Z0-9+_-]{20}$ | ||
Expect(err).To(HaveOccurred()) | ||
}) | ||
}) | ||
|
||
Context("AWS Account", func() { | ||
It("should validate correct AWS account", func() { | ||
account, err := ValidateAWSAccount("123456789012") | ||
Expect(err).To(BeNil()) | ||
Expect(account).To(Equal("123456789012")) | ||
}) | ||
|
||
It("should fail invalid AWS account", func() { | ||
_, err := ValidateAWSAccount("invalid123") // this should fail since "invalid123" does not match ^[0-9]{12}$ | ||
Expect(err).To(HaveOccurred()) | ||
}) | ||
}) | ||
|
||
Context("AWS Proxy", func() { | ||
It("should validate the correct aws proxy", func() { | ||
proxyURL, err := ValidateAWSProxy("http://www.example.com:1234") | ||
Expect(err).To(BeNil()) | ||
Expect(proxyURL).To(Equal("http://www.example.com:1234")) | ||
}) | ||
|
||
It("should fail invalid proxy url", func() { | ||
_, err := ValidateAWSProxy("https://www.example.com:1234") | ||
Expect(err).To(HaveOccurred()) | ||
}) | ||
}) | ||
|
||
Context("Vault Address", func() { | ||
It("should validate the correct vault address", func() { | ||
vaultURL, err := ValidateVaultAddress("https://vault.dev.net/") | ||
Expect(err).To(BeNil()) | ||
Expect(vaultURL).To(Equal("https://vault.dev.net/")) | ||
}) | ||
|
||
It("should fail invalid vault address", func() { | ||
_, err := ValidateVaultAddress("http://vault.dev.net/") | ||
Expect(err).To(HaveOccurred()) | ||
}) | ||
}) | ||
|
||
Context("Vault Path", func() { | ||
It("should validate the correct vault path", func() { | ||
proxyURL, err := ValidateDtVaultPath("osd-sre/dynatrace/sd-sre-grail-logs") | ||
Expect(err).To(BeNil()) | ||
Expect(proxyURL).To(Equal("osd-sre/dynatrace/sd-sre-grail-logs")) | ||
}) | ||
|
||
It("should fail invalid vault path", func() { | ||
_, err := ValidateDtVaultPath("/osd-sre/dynatrace/sd-sre-grail-logs/logs") | ||
Expect(err).ShouldNot(HaveOccurred()) | ||
}) | ||
}) | ||
}) |