Skip to content

Commit

Permalink
Merge pull request #266 from DopplerHQ/manage-environments
Browse files Browse the repository at this point in the history
Add support for creating/deleting/renaming environments
  • Loading branch information
Piccirello authored Oct 15, 2021
2 parents a0d1ec6 + 58b8c23 commit 1c431e2
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 1 deletion.
128 changes: 128 additions & 0 deletions pkg/cmd/environments.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ limitations under the License.
package cmd

import (
"errors"
"fmt"

"github.com/DopplerHQ/cli/pkg/configuration"
"github.com/DopplerHQ/cli/pkg/controllers"
"github.com/DopplerHQ/cli/pkg/http"
Expand All @@ -39,6 +42,29 @@ var environmentsGetCmd = &cobra.Command{
Run: getEnvironments,
}

var environmentsCreateCmd = &cobra.Command{
Use: "create [name] [slug]",
Short: "Create an environment",
Args: cobra.ExactArgs(2),
Run: createEnvironment,
}

var environmentsDeleteCmd = &cobra.Command{
Use: "delete [slug]",
Short: "Delete an environment",
Args: cobra.ExactArgs(1),
ValidArgsFunction: configEnvironmentIDsValidArgs,
Run: deleteEnvironment,
}

var environmentsRenameCmd = &cobra.Command{
Use: "rename [slug]",
Short: "Rename an environment",
Args: cobra.ExactArgs(1),
ValidArgsFunction: configEnvironmentIDsValidArgs,
Run: renameEnvironment,
}

func environments(cmd *cobra.Command, args []string) {
jsonFlag := utils.OutputJSON
localConfig := configuration.LocalConfig(cmd)
Expand Down Expand Up @@ -80,10 +106,112 @@ func configEnvironmentIDsValidArgs(cmd *cobra.Command, args []string, toComplete
return nil, cobra.ShellCompDirectiveNoFileComp
}

func createEnvironment(cmd *cobra.Command, args []string) {
jsonFlag := utils.OutputJSON
localConfig := configuration.LocalConfig(cmd)

utils.RequireValue("token", localConfig.Token.Value)

name := args[0]
slug := args[1]

info, err := http.CreateEnvironment(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, name, slug)
if !err.IsNil() {
utils.HandleError(err.Unwrap(), err.Message)
}

if !utils.Silent {
printer.EnvironmentInfo(info, jsonFlag)
}
}

func deleteEnvironment(cmd *cobra.Command, args []string) {
jsonFlag := utils.OutputJSON
yes := utils.GetBoolFlag(cmd, "yes")
localConfig := configuration.LocalConfig(cmd)

utils.RequireValue("token", localConfig.Token.Value)

slug := args[0]

prompt := "Delete environment"
if slug != "" {
prompt = fmt.Sprintf("%s %s", prompt, slug)
}

if yes || utils.ConfirmationPrompt(prompt, false) {
err := http.DeleteEnvironment(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, slug)
if !err.IsNil() {
utils.HandleError(err.Unwrap(), err.Message)
}

if !utils.Silent {
info, err := http.GetEnvironments(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value)
if !err.IsNil() {
utils.HandleError(err.Unwrap(), err.Message)
}

printer.EnvironmentsInfo(info, jsonFlag)
}
}
}

func renameEnvironment(cmd *cobra.Command, args []string) {
jsonFlag := utils.OutputJSON
yes := utils.GetBoolFlag(cmd, "yes")
localConfig := configuration.LocalConfig(cmd)
newName := cmd.Flag("name").Value.String()
newSlug := cmd.Flag("slug").Value.String()

utils.RequireValue("token", localConfig.Token.Value)

if newName == "" && newSlug == "" {
utils.HandleError(errors.New("command requires --name or --slug"))
}

slug := args[0]

prompt := "Rename environment"
if slug != "" {
prompt = fmt.Sprintf("%s %s", prompt, slug)
}

if !yes {
if newSlug != "" {
utils.LogWarning("Modifying your environment's slug may break your current deploys. All configs within this environment will also be renamed.")
}
yes = utils.ConfirmationPrompt(prompt, false)
}

if yes {
info, err := http.RenameEnvironment(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, slug, newName, newSlug)
if !err.IsNil() {
utils.HandleError(err.Unwrap(), err.Message)
}

if !utils.Silent {
printer.EnvironmentInfo(info, jsonFlag)
}
}
}

func init() {
environmentsGetCmd.Flags().StringP("project", "p", "", "project (e.g. backend)")
environmentsCmd.AddCommand(environmentsGetCmd)

environmentsCreateCmd.Flags().StringP("project", "p", "", "project (e.g. backend)")
environmentsCmd.AddCommand(environmentsCreateCmd)

environmentsDeleteCmd.Flags().StringP("project", "p", "", "project (e.g. backend)")
environmentsDeleteCmd.Flags().BoolP("yes", "y", false, "proceed without confirmation")
environmentsCmd.AddCommand(environmentsDeleteCmd)

environmentsRenameCmd.Flags().StringP("project", "p", "", "project (e.g. backend)")
environmentsRenameCmd.Flags().BoolP("yes", "y", false, "proceed without confirmation")
environmentsRenameCmd.Flags().String("name", "", "new name")
environmentsRenameCmd.Flags().String("slug", "", "new slug")
environmentsCmd.AddCommand(environmentsRenameCmd)

environmentsCmd.Flags().StringP("project", "p", "", "project (e.g. backend)")
rootCmd.AddCommand(environmentsCmd)
}
74 changes: 73 additions & 1 deletion pkg/http/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ func UpdateProject(host string, verifyTLS bool, apiKey string, project string, n
return projectInfo, Error{}
}

// DeleteProject create a project
// DeleteProject delete a project
func DeleteProject(host string, verifyTLS bool, apiKey string, project string) Error {
var params []queryParam
params = append(params, queryParam{Key: "project", Value: project})
Expand Down Expand Up @@ -476,6 +476,78 @@ func GetEnvironment(host string, verifyTLS bool, apiKey string, project string,
return info, Error{}
}

// CreateEnvironment create an environment
func CreateEnvironment(host string, verifyTLS bool, apiKey string, project string, name string, slug string) (models.EnvironmentInfo, Error) {
postBody := map[string]string{"project": project, "name": name, "slug": slug}
body, err := json.Marshal(postBody)
if err != nil {
return models.EnvironmentInfo{}, Error{Err: err, Message: "Invalid environment info"}
}

statusCode, _, response, err := PostRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/environments", []queryParam{}, body)
if err != nil {
return models.EnvironmentInfo{}, Error{Err: err, Message: "Unable to create environment", Code: statusCode}
}

var result map[string]interface{}
err = json.Unmarshal(response, &result)
if err != nil {
return models.EnvironmentInfo{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
}

environmentInfo := models.ParseEnvironmentInfo(result["environment"].(map[string]interface{}))
return environmentInfo, Error{}
}

// DeleteEnvironment delete an environment
func DeleteEnvironment(host string, verifyTLS bool, apiKey string, project string, environment string) Error {
var params []queryParam
params = append(params, queryParam{Key: "project", Value: project})
params = append(params, queryParam{Key: "environment", Value: environment})

statusCode, _, response, err := DeleteRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/environments/environment", params)
if err != nil {
return Error{Err: err, Message: "Unable to delete environment", Code: statusCode}
}

var result map[string]interface{}
err = json.Unmarshal(response, &result)
if err != nil {
return Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
}

return Error{}
}

// RenameEnvironment rename an environment
func RenameEnvironment(host string, verifyTLS bool, apiKey string, project string, environment string, name string, slug string) (models.EnvironmentInfo, Error) {
postBody := map[string]string{"project": project, "environment": environment}
if name != "" {
postBody["name"] = name
}
if slug != "" {
postBody["slug"] = slug
}
body, err := json.Marshal(postBody)
if err != nil {
return models.EnvironmentInfo{}, Error{Err: err, Message: "Invalid environment info"}
}

statusCode, _, response, err := PutRequest(host, verifyTLS, apiKeyHeader(apiKey), "/v3/environments/environment", []queryParam{}, body)
if err != nil {
return models.EnvironmentInfo{}, Error{Err: err, Message: "Unable to rename environment", Code: statusCode}
}

var result map[string]interface{}
err = json.Unmarshal(response, &result)
if err != nil {
return models.EnvironmentInfo{}, Error{Err: err, Message: "Unable to parse API response", Code: statusCode}
}

environmentInfo := models.ParseEnvironmentInfo(result["environment"].(map[string]interface{}))
return environmentInfo, Error{}
}

// GetConfigs get configs
func GetConfigs(host string, verifyTLS bool, apiKey string, project string) ([]models.ConfigInfo, Error) {
var params []queryParam
Expand Down
20 changes: 20 additions & 0 deletions pkg/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,26 @@ func PostRequest(host string, verifyTLS bool, headers map[string]string, uri str
return statusCode, respHeaders, body, nil
}

// PutRequest perform HTTP PUT
func PutRequest(host string, verifyTLS bool, headers map[string]string, uri string, params []queryParam, body []byte) (int, http.Header, []byte, error) {
url := fmt.Sprintf("%s%s", host, uri)
req, err := http.NewRequest("PUT", url, bytes.NewReader(body))
if err != nil {
return 0, nil, nil, err
}

for key, value := range headers {
req.Header.Set(key, value)
}

statusCode, respHeaders, body, err := performRequest(req, verifyTLS, params)
if err != nil {
return statusCode, respHeaders, body, err
}

return statusCode, respHeaders, body, nil
}

// DeleteRequest perform HTTP DELETE
func DeleteRequest(host string, verifyTLS bool, headers map[string]string, uri string, params []queryParam) (int, http.Header, []byte, error) {
url := fmt.Sprintf("%s%s", host, uri)
Expand Down

0 comments on commit 1c431e2

Please sign in to comment.