diff --git a/.goreleaser.yml b/.goreleaser.yml index 197107d9..efbb708f 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -133,7 +133,7 @@ brews: commit_author: name: "Doppler Bot" email: bot@doppler.com - folder: Formula + directory: Formula homepage: "https://doppler.com" description: "The official Doppler CLI for managing your secrets" install: |- @@ -216,4 +216,4 @@ blobs: - provider: gs bucket: dopplerhq_cli_releases - folder: "{{ .Tag }}" + directory: "{{ .Tag }}" diff --git a/pkg/cmd/enclave_secrets.go b/pkg/cmd/enclave_secrets.go index 1dc96d1f..a6e14159 100644 --- a/pkg/cmd/enclave_secrets.go +++ b/pkg/cmd/enclave_secrets.go @@ -105,6 +105,7 @@ func init() { } enclaveSecretsCmd.Flags().Bool("raw", false, "print the raw secret value without processing variables") enclaveSecretsCmd.Flags().Bool("visibility", false, "include secret visibility in table output") + enclaveSecretsCmd.Flags().Bool("type", false, "include secret type in table output") enclaveSecretsCmd.Flags().Bool("only-names", false, "only print the secret names; omit all values") enclaveSecretsGetCmd.Flags().StringP("project", "p", "", "enclave project (e.g. backend)") @@ -119,6 +120,7 @@ func init() { enclaveSecretsGetCmd.Flags().Bool("copy", false, "copy the value(s) to your clipboard") enclaveSecretsGetCmd.Flags().Bool("raw", false, "print the raw secret value without processing variables") enclaveSecretsGetCmd.Flags().Bool("visibility", false, "include secret visibility in table output") + enclaveSecretsGetCmd.Flags().Bool("type", false, "include secret type in table output") enclaveSecretsGetCmd.Flags().Bool("no-exit-on-missing-secret", false, "do not exit if unable to find a requested secret") enclaveSecretsCmd.AddCommand(enclaveSecretsGetCmd) diff --git a/pkg/cmd/secrets.go b/pkg/cmd/secrets.go index 9df433dd..5502f491 100644 --- a/pkg/cmd/secrets.go +++ b/pkg/cmd/secrets.go @@ -160,6 +160,7 @@ func secrets(cmd *cobra.Command, args []string) { jsonFlag := utils.OutputJSON raw := utils.GetBoolFlag(cmd, "raw") visibility := utils.GetBoolFlag(cmd, "visibility") + valueType := utils.GetBoolFlag(cmd, "type") onlyNames := utils.GetBoolFlag(cmd, "only-names") localConfig := configuration.LocalConfig(cmd) @@ -182,7 +183,7 @@ func secrets(cmd *cobra.Command, args []string) { utils.HandleError(parseErr, "Unable to parse API response") } - printer.Secrets(secrets, []string{}, jsonFlag, false, raw, false, visibility) + printer.Secrets(secrets, []string{}, jsonFlag, false, raw, false, visibility, valueType) } } @@ -192,6 +193,7 @@ func getSecrets(cmd *cobra.Command, args []string) { copy := utils.GetBoolFlag(cmd, "copy") raw := utils.GetBoolFlag(cmd, "raw") visibility := utils.GetBoolFlag(cmd, "visibility") + valueType := utils.GetBoolFlag(cmd, "type") exitOnMissingSecret := !utils.GetBoolFlag(cmd, "no-exit-on-missing-secret") localConfig := configuration.LocalConfig(cmd) @@ -228,7 +230,7 @@ func getSecrets(cmd *cobra.Command, args []string) { } } - printer.Secrets(secrets, args, jsonFlag, plain, raw, copy, visibility) + printer.Secrets(secrets, args, jsonFlag, plain, raw, copy, visibility, valueType) } func setSecrets(cmd *cobra.Command, args []string) { @@ -238,6 +240,8 @@ func setSecrets(cmd *cobra.Command, args []string) { localConfig := configuration.LocalConfig(cmd) visibility := cmd.Flag("visibility").Value.String() visibilityModified := visibility != "" + valueType := cmd.Flag("type").Value.String() + valueTypeModified := valueType != "" utils.RequireValue("token", localConfig.Token.Value) @@ -318,6 +322,11 @@ func setSecrets(cmd *cobra.Command, args []string) { if visibilityModified { changeRequest.Visibility = &visibility } + if valueTypeModified { + changeRequest.ValueType = &models.SecretValueType{ + Type: valueType, + } + } changeRequests = append(changeRequests, changeRequest) } else if len(args) == 2 && !strings.Contains(args[0], "=") { // format: 'doppler secrets set KEY value' @@ -331,6 +340,11 @@ func setSecrets(cmd *cobra.Command, args []string) { if visibilityModified { changeRequest.Visibility = &visibility } + if valueTypeModified { + changeRequest.ValueType = &models.SecretValueType{ + Type: valueType, + } + } changeRequests = append(changeRequests, changeRequest) } else { // format: 'doppler secrets set KEY=value' @@ -351,6 +365,11 @@ func setSecrets(cmd *cobra.Command, args []string) { if visibilityModified { changeRequest.Visibility = &visibility } + if valueTypeModified { + changeRequest.ValueType = &models.SecretValueType{ + Type: valueType, + } + } changeRequests = append(changeRequests, changeRequest) } } @@ -361,7 +380,7 @@ func setSecrets(cmd *cobra.Command, args []string) { } if !utils.Silent { - printer.Secrets(response, keys, jsonFlag, false, raw, false, visibilityModified) + printer.Secrets(response, keys, jsonFlag, false, raw, false, visibilityModified, valueTypeModified) } } @@ -393,7 +412,7 @@ func uploadSecrets(cmd *cobra.Command, args []string) { } if !utils.Silent { - printer.Secrets(response, []string{}, jsonFlag, false, raw, false, false) + printer.Secrets(response, []string{}, jsonFlag, false, raw, false, false, false) } } @@ -417,7 +436,7 @@ func deleteSecrets(cmd *cobra.Command, args []string) { } if !utils.Silent { - printer.Secrets(response, []string{}, jsonFlag, false, raw, false, false) + printer.Secrets(response, []string{}, jsonFlag, false, raw, false, false, false) } } } @@ -627,6 +646,7 @@ func init() { } secretsCmd.Flags().Bool("raw", false, "print the raw secret value without processing variables") secretsCmd.Flags().Bool("visibility", false, "include secret visibility in table output") + secretsCmd.Flags().Bool("type", false, "include secret type in table output") secretsCmd.Flags().Bool("only-names", false, "only print the secret names; omit all values") secretsGetCmd.Flags().StringP("project", "p", "", "project (e.g. backend)") @@ -641,6 +661,7 @@ func init() { secretsGetCmd.Flags().Bool("copy", false, "copy the value(s) to your clipboard") secretsGetCmd.Flags().Bool("raw", false, "print the raw secret value without processing variables") secretsGetCmd.Flags().Bool("visibility", false, "include secret visibility in table output") + secretsGetCmd.Flags().Bool("type", false, "include secret type in table output") secretsGetCmd.Flags().Bool("no-exit-on-missing-secret", false, "do not exit if unable to find a requested secret") secretsCmd.AddCommand(secretsGetCmd) @@ -654,7 +675,8 @@ func init() { } secretsSetCmd.Flags().Bool("raw", false, "print the raw secret value without processing variables") secretsSetCmd.Flags().Bool("no-interactive", false, "do not allow entering secret value via interactive mode") - secretsSetCmd.Flags().StringP("visibility", "", "", "visibility (e.g. masked, unmasked, or restricted)") + secretsSetCmd.Flags().String("visibility", "", "visibility (e.g. masked, unmasked, or restricted)") + secretsSetCmd.Flags().String("type", "", "value type (e.g. string, decimal, etc)") secretsCmd.AddCommand(secretsSetCmd) secretsUploadCmd.Flags().StringP("project", "p", "", "project (e.g. backend)") diff --git a/pkg/models/api.go b/pkg/models/api.go index bf9a3115..bcc6898c 100644 --- a/pkg/models/api.go +++ b/pkg/models/api.go @@ -15,27 +15,35 @@ limitations under the License. */ package models +type SecretValueType struct { + Type string `json:"type"` +} + // ComputedSecret holds all info about a secret type ComputedSecret struct { - Name string `json:"name"` - RawValue *string `json:"raw"` - ComputedValue *string `json:"computed"` - RawVisibility string `json:"rawVisibility"` - ComputedVisibility string `json:"computedVisibility"` - Note string `json:"note"` + Name string `json:"name"` + RawValue *string `json:"raw"` + ComputedValue *string `json:"computed"` + RawVisibility string `json:"rawVisibility"` + ComputedVisibility string `json:"computedVisibility"` + RawValueType SecretValueType `json:"rawValueType"` + ComputedValueType SecretValueType `json:"computedValueType"` + Note string `json:"note"` } // ChangeRequest can be used to smartly update secrets type ChangeRequest struct { - Name string `json:"name"` - OriginalName interface{} `json:"originalName"` - Value interface{} `json:"value"` - OriginalValue interface{} `json:"originalValue,omitempty"` - Visibility *string `json:"visibility,omitempty"` - OriginalVisibility *string `json:"originalVisibility,omitempty"` - ShouldPromote *bool `json:"shouldPromote,omitempty"` - ShouldDelete *bool `json:"shouldDelete,omitempty"` - ShouldConverge *bool `json:"shouldConverge,omitempty"` + Name string `json:"name"` + OriginalName interface{} `json:"originalName"` + Value interface{} `json:"value"` + OriginalValue interface{} `json:"originalValue,omitempty"` + Visibility *string `json:"visibility,omitempty"` + OriginalVisibility *string `json:"originalVisibility,omitempty"` + ValueType *SecretValueType `json:"valueType,omitempty"` + OriginalValueType *SecretValueType `json:"originalValueType,omitempty"` + ShouldPromote *bool `json:"shouldPromote,omitempty"` + ShouldDelete *bool `json:"shouldDelete,omitempty"` + ShouldConverge *bool `json:"shouldConverge,omitempty"` } // SecretNote contains a secret and its note @@ -141,11 +149,13 @@ type APISecretResponse struct { // APISecret is the object the API returns for a given secret type APISecret struct { - RawValue *string `json:"raw"` - ComputedValue *string `json:"computed"` - RawVisibility string `json:"rawVisibility"` - ComputedVisibility string `json:"computedVisibility"` - Note string `json:"note"` + RawValue *string `json:"raw"` + ComputedValue *string `json:"computed"` + RawVisibility string `json:"rawVisibility"` + ComputedVisibility string `json:"computedVisibility"` + RawValueType SecretValueType `json:"rawValueType"` + ComputedValueType SecretValueType `json:"computedValueType"` + Note string `json:"note"` } type ActorInfo struct { diff --git a/pkg/models/parse.go b/pkg/models/parse.go index f5f35ffe..b9c72e6b 100644 --- a/pkg/models/parse.go +++ b/pkg/models/parse.go @@ -240,6 +240,8 @@ func ConvertAPIToComputedSecrets(apiSecrets map[string]APISecret) map[string]Com ComputedValue: secret.ComputedValue, RawVisibility: secret.RawVisibility, ComputedVisibility: secret.ComputedVisibility, + RawValueType: secret.RawValueType, + ComputedValueType: secret.ComputedValueType, Note: secret.Note, } } diff --git a/pkg/printer/enclave.go b/pkg/printer/enclave.go index 2ce16a36..e025a139 100644 --- a/pkg/printer/enclave.go +++ b/pkg/printer/enclave.go @@ -202,7 +202,7 @@ func ProjectInfo(info models.ProjectInfo, jsonFlag bool) { } // Secrets print secrets -func Secrets(secrets map[string]models.ComputedSecret, secretsToPrint []string, jsonFlag bool, plain bool, raw bool, copy bool, visibility bool) { +func Secrets(secrets map[string]models.ComputedSecret, secretsToPrint []string, jsonFlag bool, plain bool, raw bool, copy bool, visibility bool, valueType bool) { if len(secretsToPrint) == 0 { for name := range secrets { secretsToPrint = append(secretsToPrint, name) @@ -234,6 +234,7 @@ func Secrets(secrets map[string]models.ComputedSecret, secretsToPrint []string, secretsMap[name] = map[string]interface{}{ "note": secrets[name].Note, "computedVisibility": secrets[name].ComputedVisibility, + "computedValueType": secrets[name].ComputedValueType, } if secrets[name].ComputedValue != nil { @@ -244,6 +245,7 @@ func Secrets(secrets map[string]models.ComputedSecret, secretsToPrint []string, if raw { secretsMap[name]["rawVisibility"] = secrets[name].RawVisibility + secretsMap[name]["rawValueType"] = secrets[name].RawValueType if secrets[name].RawValue != nil { secretsMap[name]["raw"] = *secrets[name].RawValue } else { @@ -290,11 +292,17 @@ func Secrets(secrets map[string]models.ComputedSecret, secretsToPrint []string, if visibility { headers = append(headers, "visibility") } + if valueType { + headers = append(headers, "type") + } headers = append(headers, "value") if raw { if visibility { headers = append(headers, "raw visibility") } + if valueType { + headers = append(headers, "raw type") + } headers = append(headers, "raw value") } headers = append(headers, "note") @@ -312,6 +320,9 @@ func Secrets(secrets map[string]models.ComputedSecret, secretsToPrint []string, if visibility { row = append(row, secret.ComputedVisibility) } + if valueType { + row = append(row, secret.ComputedValueType.Type) + } row = append(row, computedValue) if raw { var rawValue string @@ -323,6 +334,9 @@ func Secrets(secrets map[string]models.ComputedSecret, secretsToPrint []string, if visibility { row = append(row, secret.RawVisibility) } + if valueType { + row = append(row, secret.RawValueType.Type) + } row = append(row, rawValue) }