From ea9ea26fcabac7104b7684b22e1f4635fd0564a6 Mon Sep 17 00:00:00 2001 From: Adam Abdelaziz Date: Thu, 18 Jul 2024 00:43:25 +0000 Subject: [PATCH] Add environment item management commands --- cmd/cocli/createEnvironmentVariable.go | 96 +++++++++++++++++++++++ cmd/cocli/deleteEnvironmentVariable.go | 49 ++++++++++++ cmd/cocli/deployEnvironment.go | 2 +- cmd/cocli/environmentVariables.go | 18 +++++ cmd/cocli/getEnvironmentVariableValue.go | 44 +++++++++++ cmd/cocli/listEnvironmentVariables.go | 80 +++++++++++++++++++ cmd/cocli/root.go | 1 + cmd/cocli/upsertEnvironmentVariables.go | 99 ++++++++++++++++++++++++ cocli_version.txt | 2 +- go.mod | 1 + go.sum | 2 + pkg/cocli/cocli.go | 2 +- 12 files changed, 393 insertions(+), 3 deletions(-) create mode 100644 cmd/cocli/createEnvironmentVariable.go create mode 100644 cmd/cocli/deleteEnvironmentVariable.go create mode 100644 cmd/cocli/environmentVariables.go create mode 100644 cmd/cocli/getEnvironmentVariableValue.go create mode 100644 cmd/cocli/listEnvironmentVariables.go create mode 100644 cmd/cocli/upsertEnvironmentVariables.go diff --git a/cmd/cocli/createEnvironmentVariable.go b/cmd/cocli/createEnvironmentVariable.go new file mode 100644 index 0000000..d0ffaae --- /dev/null +++ b/cmd/cocli/createEnvironmentVariable.go @@ -0,0 +1,96 @@ +package cocli + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + + "github.com/coherenceplatform/cocli/pkg/cocli" + "github.com/spf13/cobra" +) + +var createEnvVarCmd = &cobra.Command{ + Use: "create", + Short: "Create a new environment variable", + Long: "Create a new environment variable for a specific environment or collection.", + Run: func(cmd *cobra.Command, args []string) { + targetEnvName, _ := cmd.Flags().GetString("target_env_name") + itemType, _ := cmd.Flags().GetString("type") + collectionID, _ := cmd.Flags().GetInt("collection_id") + environmentID, _ := cmd.Flags().GetInt("environment_id") + serviceName, _ := cmd.Flags().GetString("service_name") + value, _ := cmd.Flags().GetString("value") + secretID, _ := cmd.Flags().GetString("secret_id") + outputName, _ := cmd.Flags().GetString("output_name") + alias, _ := cmd.Flags().GetString("alias") + + if targetEnvName == "" { + fmt.Println("Error: target_env_name is required") + return + } + + if collectionID == 0 && environmentID == 0 { + fmt.Println("Error: either collection_id or environment_id is required") + return + } + + payload := map[string]interface{}{ + "target_env_name": targetEnvName, + "type": itemType, + "service_name": serviceName, + "value": value, + "secret_id": secretID, + "output_name": outputName, + "alias": alias, + } + + if collectionID != 0 { + payload["collection_id"] = collectionID + } + if environmentID != 0 { + payload["environment_id"] = environmentID + } + + jsonPayload, err := json.Marshal(payload) + if err != nil { + fmt.Println("Error creating JSON payload:", err) + return + } + + createURL := fmt.Sprintf("%s/api/v1/environment_items", cocli.GetCoherenceDomain()) + + res, err := cocli.CoherenceApiRequest( + "POST", + createURL, + bytes.NewBuffer(jsonPayload), + ) + if err != nil { + fmt.Println("Error making request:", err) + return + } + defer res.Body.Close() + + bodyBytes, err := io.ReadAll(res.Body) + if err != nil { + fmt.Println("Error reading response:", err) + return + } + + fmt.Println(cocli.FormatJSONOutput(bodyBytes)) + }, +} + +func init() { + createEnvVarCmd.Flags().String("target_env_name", "", "Name of the environment variable (required)") + createEnvVarCmd.Flags().String("type", "standard", "Type of the environment variable (standard, secret, output, alias)") + createEnvVarCmd.Flags().Int("collection_id", 0, "ID of the collection") + createEnvVarCmd.Flags().Int("environment_id", 0, "ID of the environment") + createEnvVarCmd.Flags().String("service_name", "", "Name of the service") + createEnvVarCmd.Flags().String("value", "", "Value of the environment variable") + createEnvVarCmd.Flags().String("secret_id", "", "ID of the secret (for secret type)") + createEnvVarCmd.Flags().String("output_name", "", "Name of the output (for output type)") + createEnvVarCmd.Flags().String("alias", "", "Alias (for alias type)") + + createEnvVarCmd.MarkFlagRequired("target_env_name") +} \ No newline at end of file diff --git a/cmd/cocli/deleteEnvironmentVariable.go b/cmd/cocli/deleteEnvironmentVariable.go new file mode 100644 index 0000000..4c53563 --- /dev/null +++ b/cmd/cocli/deleteEnvironmentVariable.go @@ -0,0 +1,49 @@ +package cocli + +import ( + "fmt" + "io" + + "github.com/coherenceplatform/cocli/pkg/cocli" + "github.com/spf13/cobra" +) + +var deleteEnvVarCmd = &cobra.Command{ + Use: "delete ", + Short: "Delete an environment variable", + Long: "Delete an environment variable by its ID.", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + environmentItemID := args[0] + + deleteURL := fmt.Sprintf( + "%s/api/v1/environment_items/%s", + cocli.GetCoherenceDomain(), + environmentItemID, + ) + + res, err := cocli.CoherenceApiRequest( + "DELETE", + deleteURL, + nil, + ) + if err != nil { + fmt.Println("Error making request:", err) + return + } + defer res.Body.Close() + + if res.StatusCode == 204 { + fmt.Printf("Environment variable with ID %s has been successfully deleted.\n", environmentItemID) + return + } + + bodyBytes, err := io.ReadAll(res.Body) + if err != nil { + fmt.Println("Error reading response:", err) + return + } + + fmt.Println(cocli.FormatJSONOutput(bodyBytes)) + }, +} diff --git a/cmd/cocli/deployEnvironment.go b/cmd/cocli/deployEnvironment.go index b99fc26..bb7d039 100644 --- a/cmd/cocli/deployEnvironment.go +++ b/cmd/cocli/deployEnvironment.go @@ -92,4 +92,4 @@ var deployCmd = &cobra.Command{ fmt.Println(cocli.FormatJSONOutput(bodyBytes)) }, -} \ No newline at end of file +} diff --git a/cmd/cocli/environmentVariables.go b/cmd/cocli/environmentVariables.go new file mode 100644 index 0000000..52df2af --- /dev/null +++ b/cmd/cocli/environmentVariables.go @@ -0,0 +1,18 @@ +package cocli + +import ( + "github.com/spf13/cobra" +) + +var envVarCmd = &cobra.Command{ + Use: "env-vars", + Short: "Coherence environment variable management commands", +} + +func init() { + envVarCmd.AddCommand(listEnvVarsCmd) + envVarCmd.AddCommand(createEnvVarCmd) + envVarCmd.AddCommand(deleteEnvVarCmd) + envVarCmd.AddCommand(upsertEnvVarsCmd) + envVarCmd.AddCommand(getEnvVarValueCmd) +} diff --git a/cmd/cocli/getEnvironmentVariableValue.go b/cmd/cocli/getEnvironmentVariableValue.go new file mode 100644 index 0000000..61d921e --- /dev/null +++ b/cmd/cocli/getEnvironmentVariableValue.go @@ -0,0 +1,44 @@ +package cocli + +import ( + "fmt" + "io" + + "github.com/coherenceplatform/cocli/pkg/cocli" + "github.com/spf13/cobra" +) + +var getEnvVarValueCmd = &cobra.Command{ + Use: "get-value ", + Short: "Get the value of an environment variable", + Long: "Retrieve the value of a specific environment variable by its ID.", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + environmentItemID := args[0] + + getValueURL := fmt.Sprintf( + "%s/api/v1/environment_items/%s/value", + cocli.GetCoherenceDomain(), + environmentItemID, + ) + + res, err := cocli.CoherenceApiRequest( + "GET", + getValueURL, + nil, + ) + if err != nil { + fmt.Println("Error making request:", err) + return + } + defer res.Body.Close() + + bodyBytes, err := io.ReadAll(res.Body) + if err != nil { + fmt.Println("Error reading response:", err) + return + } + + fmt.Println(cocli.FormatJSONOutput(bodyBytes)) + }, +} diff --git a/cmd/cocli/listEnvironmentVariables.go b/cmd/cocli/listEnvironmentVariables.go new file mode 100644 index 0000000..d4ee681 --- /dev/null +++ b/cmd/cocli/listEnvironmentVariables.go @@ -0,0 +1,80 @@ +package cocli + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/coherenceplatform/cocli/pkg/cocli" + "github.com/spf13/cobra" +) + +var listEnvVarsCmd = &cobra.Command{ + Use: "list", + Short: "List environment variables", + Long: "List all environment variables for a specific environment or collection.", + Run: func(cmd *cobra.Command, args []string) { + environmentID, _ := cmd.Flags().GetInt("environment_id") + collectionID, _ := cmd.Flags().GetInt("collection_id") + + if environmentID == 0 && collectionID == 0 { + fmt.Println("Error: Either environment_id or collection_id must be provided") + return + } + + if environmentID != 0 && collectionID != 0 { + fmt.Println("Error: Please provide either environment_id or collection_id, not both") + return + } + + var url string + if environmentID != 0 { + url = fmt.Sprintf("%s/api/v1/environments/%d", cocli.GetCoherenceDomain(), environmentID) + } else { + url = fmt.Sprintf("%s/api/v1/collections/%d", cocli.GetCoherenceDomain(), collectionID) + } + + res, err := cocli.CoherenceApiRequest("GET", url, nil) + if err != nil { + fmt.Println("Error making request:", err) + return + } + defer res.Body.Close() + + bodyBytes, err := io.ReadAll(res.Body) + if err != nil { + fmt.Println("Error reading response:", err) + return + } + + var responseData map[string]interface{} + err = json.Unmarshal(bodyBytes, &responseData) + if err != nil { + fmt.Println("Error parsing JSON response:", err) + return + } + + output := make(map[string]interface{}) + + if envItems, ok := responseData["environment_items"]; ok { + output["environment_items"] = envItems + } + + if managedEnvItems, ok := responseData["managed_environment_items"]; ok { + output["managed_environment_items"] = managedEnvItems + } + + outputJSON, err := json.Marshal(output) + if err != nil { + fmt.Println("Error creating JSON output:", err) + return + } + + fmt.Println(cocli.FormatJSONOutput(outputJSON)) + }, +} + +func init() { + listEnvVarsCmd.Flags().Int("environment_id", 0, "ID of the environment") + listEnvVarsCmd.Flags().Int("collection_id", 0, "ID of the collection") +} diff --git a/cmd/cocli/root.go b/cmd/cocli/root.go index d124dfe..067aa6b 100644 --- a/cmd/cocli/root.go +++ b/cmd/cocli/root.go @@ -27,5 +27,6 @@ func init() { rootCmd.AddCommand(collectionCmd) rootCmd.AddCommand(cncCmd) rootCmd.AddCommand(environmentCmd) + rootCmd.AddCommand(envVarCmd) cocli.RunCliVersionCheck() } diff --git a/cmd/cocli/upsertEnvironmentVariables.go b/cmd/cocli/upsertEnvironmentVariables.go new file mode 100644 index 0000000..be25695 --- /dev/null +++ b/cmd/cocli/upsertEnvironmentVariables.go @@ -0,0 +1,99 @@ +package cocli + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + + "github.com/coherenceplatform/cocli/pkg/cocli" + "github.com/spf13/cobra" +) + +var upsertEnvVarsCmd = &cobra.Command{ + Use: "upsert", + Short: "Upsert environment variables", + Long: "Bulk upsert environment variables from a .env file or a string representation.", + Run: func(cmd *cobra.Command, args []string) { + collectionID, _ := cmd.Flags().GetInt("collection_id") + environmentID, _ := cmd.Flags().GetInt("environment_id") + serviceName, _ := cmd.Flags().GetString("service_name") + envType, _ := cmd.Flags().GetString("type") + envFile, _ := cmd.Flags().GetString("file") + envString, _ := cmd.Flags().GetString("env-string") + + if collectionID == 0 && environmentID == 0 { + fmt.Println("Error: either collection_id or environment_id is required") + return + } + + var items string + var err error + + if envFile != "" { + itemsBytes, err := os.ReadFile(envFile) + if err != nil { + fmt.Println("Error reading .env file:", err) + return + } + items = string(itemsBytes) + } else if envString != "" { + items = envString + } else { + fmt.Println("Error: either --file or --env-string must be provided") + return + } + + payload := map[string]interface{}{ + "items": items, + "type": envType, + } + + if collectionID != 0 { + payload["collection_id"] = collectionID + } + if environmentID != 0 { + payload["environment_id"] = environmentID + } + if serviceName != "" { + payload["service_name"] = serviceName + } + + jsonPayload, err := json.Marshal(payload) + if err != nil { + fmt.Println("Error creating JSON payload:", err) + return + } + + upsertURL := fmt.Sprintf("%s/api/v1/environment_items/bulk", cocli.GetCoherenceDomain()) + + res, err := cocli.CoherenceApiRequest( + "POST", + upsertURL, + bytes.NewBuffer(jsonPayload), + ) + if err != nil { + fmt.Println("Error making request:", err) + return + } + defer res.Body.Close() + + bodyBytes, err := io.ReadAll(res.Body) + if err != nil { + fmt.Println("Error reading response:", err) + return + } + + fmt.Println(cocli.FormatJSONOutput(bodyBytes)) + }, +} + +func init() { + upsertEnvVarsCmd.Flags().Int("collection_id", 0, "ID of the collection") + upsertEnvVarsCmd.Flags().Int("environment_id", 0, "ID of the environment") + upsertEnvVarsCmd.Flags().String("service_name", "", "Name of the service") + upsertEnvVarsCmd.Flags().String("type", "standard", "Type of the environment variables (standard or secret)") + upsertEnvVarsCmd.Flags().String("file", "", "Path to the .env file") + upsertEnvVarsCmd.Flags().String("env-string", "", "String representation of environment variables") +} diff --git a/cocli_version.txt b/cocli_version.txt index e4c0d46..1cc5f65 100644 --- a/cocli_version.txt +++ b/cocli_version.txt @@ -1 +1 @@ -1.0.3 \ No newline at end of file +1.1.0 \ No newline at end of file diff --git a/go.mod b/go.mod index d208d28..17716de 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( require ( github.com/golang/protobuf v1.5.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/net v0.23.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index ade247e..cbb079b 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= diff --git a/pkg/cocli/cocli.go b/pkg/cocli/cocli.go index 9ee77f6..545c448 100644 --- a/pkg/cocli/cocli.go +++ b/pkg/cocli/cocli.go @@ -24,7 +24,7 @@ var prodConfig = &CocliConfig{ CoherenceDomain: "https://beta.withcoherence.com", } -const cliVersion = "1.0.3" +const cliVersion = "1.1.0" func GetCliConfig() CocliConfig { if strings.ToLower(os.Getenv("COHERENCE_ENVIRONMENT")) == "review" {