Skip to content

Commit

Permalink
Add ability to modify inheritance related properties
Browse files Browse the repository at this point in the history
  • Loading branch information
apazzolini committed Nov 25, 2024
1 parent 26c11db commit 98ecf0b
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 14 deletions.
73 changes: 59 additions & 14 deletions pkg/cmd/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,19 @@ var configsDeleteCmd = &cobra.Command{
var configsUpdateCmd = &cobra.Command{
Use: "update [config]",
Short: "Update a config",
Long: "Update properties about a config, such as its name, inheritability flag, and inheritances",
Args: cobra.MaximumNArgs(1),
ValidArgsFunction: configNamesValidArgs,
Run: updateConfigs,
Example: `Updating a config's name
$ doppler configs update --project proj --config dev_branch --name dev_branch2
Enabling a config to be inherited
$ doppler configs update --project proj --config dev --inheritable true
Configuring which configs the given config inherits
Note: The inherits flag accepts a comma separated list of PROJ_NAME.CONF_NAME
$ doppler configs update --project proj --config dev --inherits "shared-db.dev,shared-api.dev"`,
}

var configsLockCmd = &cobra.Command{
Expand Down Expand Up @@ -196,34 +206,70 @@ func deleteConfigs(cmd *cobra.Command, args []string) {

func updateConfigs(cmd *cobra.Command, args []string) {
jsonFlag := utils.OutputJSON

nameSet := cmd.Flags().Changed("name")
inheritableSet := cmd.Flags().Changed("inheritable")
inheritsSet := cmd.Flags().Changed("inherits")

if (nameSet && (inheritableSet || inheritsSet)) || (inheritableSet && inheritsSet) {
utils.HandleError(fmt.Errorf("Exactly one of name, inheritable, and inherits must be specified"))
}

name := cmd.Flag("name").Value.String()
inheritable := utils.GetBoolFlag(cmd, "inheritable")
inherits := cmd.Flag("inherits").Value.String()
yes := utils.GetBoolFlag(cmd, "yes")
localConfig := configuration.LocalConfig(cmd)

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

config := localConfig.EnclaveConfig.Value
if len(args) > 0 {
config = args[0]
}

if !yes {
utils.PrintWarning("Renaming this config may break your current deploys.")
if !utils.ConfirmationPrompt("Continue?", false) {
utils.Log("Aborting")
return
if nameSet {
if !yes {
utils.PrintWarning("Renaming this config may break your current deploys.")
if !utils.ConfirmationPrompt("Continue?", false) {
utils.Log("Aborting")
return
}
}

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

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

}

info, err := http.UpdateConfig(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, config, name)
if !err.IsNil() {
utils.HandleError(err.Unwrap(), err.Message)
if inheritableSet {
info, err := http.UpdateConfigInheritable(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, config, inheritable)
if !err.IsNil() {
utils.HandleError(err.Unwrap(), err.Message)
}

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

if !utils.Silent {
printer.ConfigInfo(info, jsonFlag)
if inheritsSet {
info, err := http.UpdateConfigInherits(localConfig.APIHost.Value, utils.GetBool(localConfig.VerifyTLS.Value, true), localConfig.Token.Value, localConfig.EnclaveProject.Value, config, inherits)
if !err.IsNil() {
utils.HandleError(err.Unwrap(), err.Message)
}

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

}

func lockConfigs(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -395,9 +441,8 @@ func init() {
utils.HandleError(err)
}
configsUpdateCmd.Flags().String("name", "", "config name")
if err := configsUpdateCmd.MarkFlagRequired("name"); err != nil {
utils.HandleError(err)
}
configsUpdateCmd.Flags().Bool("inheritable", false, "toggle config inheritability")
configsUpdateCmd.Flags().String("inherits", "", "configs to inherit (e.g. \"proj2.prd,shared.prd\")")
configsUpdateCmd.Flags().BoolP("yes", "y", false, "proceed without confirmation")
configsCmd.AddCommand(configsUpdateCmd)

Expand Down
84 changes: 84 additions & 0 deletions pkg/http/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,90 @@ func UpdateConfig(host string, verifyTLS bool, apiKey string, project string, co
return info, Error{}
}

func UpdateConfigInheritable(host string, verifyTLS bool, apiKey string, project string, config string, inheritable bool) (models.ConfigInfo, Error) {
postBody := map[string]interface{}{"inheritable": inheritable}
body, err := json.Marshal(postBody)
if err != nil {
return models.ConfigInfo{}, Error{Err: err, Message: "Invalid config info"}
}

var params []queryParam
params = append(params, queryParam{Key: "project", Value: project})
params = append(params, queryParam{Key: "config", Value: config})

url, err := generateURL(host, "/v3/configs/config/inheritable", params)
if err != nil {
return models.ConfigInfo{}, Error{Err: err, Message: "Unable to generate url"}
}

statusCode, _, response, err := PostRequest(url, verifyTLS, apiKeyHeader(apiKey), body)
if err != nil {
return models.ConfigInfo{}, Error{Err: err, Message: "Unable to update config", Code: statusCode}
}

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

configInfo, ok := result["config"].(map[string]interface{})
if !ok {
return models.ConfigInfo{}, Error{Err: fmt.Errorf("Unexpected type parsing config info, expected map[string]interface{}, got %T", result["config"]), Message: "Unable to parse API response", Code: statusCode}
}
info := models.ParseConfigInfo(configInfo)
return info, Error{}
}

func UpdateConfigInherits(host string, verifyTLS bool, apiKey string, project string, config string, inherits string) (models.ConfigInfo, Error) {
inheritsObj := []models.ConfigDescriptor{}

if len(inherits) > 0 {
configDescriptors := strings.Split(inherits, ",")
for _, cd := range configDescriptors {
parts := strings.SplitN(cd, ".", 2)
if len(parts) != 2 {
return models.ConfigInfo{}, Error{Message: "Config descriptors must match the format \"projectSlug.configName\""}
}
inheritsObj = append(inheritsObj, models.ConfigDescriptor{ProjectSlug: parts[0], ConfigName: parts[1]})
}
}

postBody := map[string]interface{}{"inherits": inheritsObj}
body, err := json.Marshal(postBody)

if err != nil {
return models.ConfigInfo{}, Error{Err: err, Message: "Invalid config info"}
}

var params []queryParam
params = append(params, queryParam{Key: "project", Value: project})
params = append(params, queryParam{Key: "config", Value: config})

url, err := generateURL(host, "/v3/configs/config/inherits", params)
if err != nil {
return models.ConfigInfo{}, Error{Err: err, Message: "Unable to generate url"}
}

statusCode, _, response, err := PostRequest(url, verifyTLS, apiKeyHeader(apiKey), body)
if err != nil {
return models.ConfigInfo{}, Error{Err: err, Message: "Unable to update config", Code: statusCode}
}

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

configInfo, ok := result["config"].(map[string]interface{})
if !ok {
return models.ConfigInfo{}, Error{Err: fmt.Errorf("Unexpected type parsing config info, expected map[string]interface{}, got %T", result["config"]), Message: "Unable to parse API response", Code: statusCode}
}
info := models.ParseConfigInfo(configInfo)
return info, Error{}
}

// GetActivityLogs get activity logs
func GetActivityLogs(host string, verifyTLS bool, apiKey string, page int, number int) ([]models.ActivityLog, Error) {
var params []queryParam
Expand Down

0 comments on commit 98ecf0b

Please sign in to comment.