-
Notifications
You must be signed in to change notification settings - Fork 168
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add tag read, write, and delete commands (#507)
The new commands are for reading, writing, and deleting tags on the underlying resources representing secrets. For now, the commands are only implemented for SSM parameters.
- Loading branch information
Showing
14 changed files
with
768 additions
and
13 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
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,74 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
analytics "github.com/segmentio/analytics-go/v3" | ||
"github.com/segmentio/chamber/v2/store" | ||
"github.com/segmentio/chamber/v2/utils" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
// tagWriteCmd represents the tag read command | ||
tagDeleteCmd = &cobra.Command{ | ||
Use: "delete <service> <key> <tag key>...", | ||
Short: "Delete tags for a specific secret", | ||
Args: cobra.MinimumNArgs(3), | ||
RunE: tagDelete, | ||
} | ||
) | ||
|
||
func init() { | ||
tagCmd.AddCommand(tagDeleteCmd) | ||
} | ||
|
||
func tagDelete(cmd *cobra.Command, args []string) error { | ||
service := utils.NormalizeService(args[0]) | ||
if err := validateService(service); err != nil { | ||
return fmt.Errorf("Failed to validate service: %w", err) | ||
} | ||
|
||
key := utils.NormalizeKey(args[1]) | ||
if err := validateKey(key); err != nil { | ||
return fmt.Errorf("Failed to validate key: %w", err) | ||
} | ||
|
||
tagKeys := make([]string, len(args)-2) | ||
for i, tagArg := range args[2:] { | ||
if err := validateTag(tagArg, "dummy"); err != nil { | ||
return fmt.Errorf("Failed to validate tag key %s: %w", tagArg, err) | ||
} | ||
tagKeys[i] = tagArg | ||
} | ||
|
||
if analyticsEnabled && analyticsClient != nil { | ||
_ = analyticsClient.Enqueue(analytics.Track{ | ||
UserId: username, | ||
Event: "Ran Command", | ||
Properties: analytics.NewProperties(). | ||
Set("command", "tag delete"). | ||
Set("chamber-version", chamberVersion). | ||
Set("service", service). | ||
Set("key", key). | ||
Set("backend", backend), | ||
}) | ||
} | ||
|
||
secretStore, err := getSecretStore(cmd.Context()) | ||
if err != nil { | ||
return fmt.Errorf("Failed to get secret store: %w", err) | ||
} | ||
|
||
secretId := store.SecretId{ | ||
Service: service, | ||
Key: key, | ||
} | ||
|
||
err = secretStore.DeleteTags(cmd.Context(), secretId, tagKeys) | ||
if err != nil { | ||
return fmt.Errorf("Failed to delete tags: %w", err) | ||
} | ||
|
||
return 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,79 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"text/tabwriter" | ||
|
||
analytics "github.com/segmentio/analytics-go/v3" | ||
"github.com/segmentio/chamber/v2/store" | ||
"github.com/segmentio/chamber/v2/utils" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
// tagReadCmd represents the tag read command | ||
tagReadCmd = &cobra.Command{ | ||
Use: "read <service> <key>", | ||
Short: "Read tags for a specific secret", | ||
Args: cobra.ExactArgs(2), | ||
RunE: tagRead, | ||
} | ||
) | ||
|
||
func init() { | ||
tagCmd.AddCommand(tagReadCmd) | ||
} | ||
|
||
func tagRead(cmd *cobra.Command, args []string) error { | ||
service := utils.NormalizeService(args[0]) | ||
if err := validateService(service); err != nil { | ||
return fmt.Errorf("Failed to validate service: %w", err) | ||
} | ||
|
||
key := utils.NormalizeKey(args[1]) | ||
if err := validateKey(key); err != nil { | ||
return fmt.Errorf("Failed to validate key: %w", err) | ||
} | ||
|
||
if analyticsEnabled && analyticsClient != nil { | ||
_ = analyticsClient.Enqueue(analytics.Track{ | ||
UserId: username, | ||
Event: "Ran Command", | ||
Properties: analytics.NewProperties(). | ||
Set("command", "tag read"). | ||
Set("chamber-version", chamberVersion). | ||
Set("service", service). | ||
Set("key", key). | ||
Set("backend", backend), | ||
}) | ||
} | ||
|
||
secretStore, err := getSecretStore(cmd.Context()) | ||
if err != nil { | ||
return fmt.Errorf("Failed to get secret store: %w", err) | ||
} | ||
|
||
secretId := store.SecretId{ | ||
Service: service, | ||
Key: key, | ||
} | ||
|
||
tags, err := secretStore.ReadTags(cmd.Context(), secretId) | ||
if err != nil { | ||
return fmt.Errorf("Failed to read tags: %w", err) | ||
} | ||
|
||
if quiet { | ||
fmt.Fprintf(os.Stdout, "%s\n", tags) | ||
return nil | ||
} | ||
|
||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 2, '\t', 0) | ||
fmt.Fprintln(w, "Key\tValue") | ||
for k, v := range tags { | ||
fmt.Fprintf(w, "%s\t%s\n", k, v) | ||
} | ||
w.Flush() | ||
return 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,95 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strings" | ||
"text/tabwriter" | ||
|
||
analytics "github.com/segmentio/analytics-go/v3" | ||
"github.com/segmentio/chamber/v2/store" | ||
"github.com/segmentio/chamber/v2/utils" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
deleteOtherTags bool | ||
|
||
// tagWriteCmd represents the tag read command | ||
tagWriteCmd = &cobra.Command{ | ||
Use: "write <service> <key> <tag>...", | ||
Short: "Write tags for a specific secret", | ||
Args: cobra.MinimumNArgs(3), | ||
RunE: tagWrite, | ||
} | ||
) | ||
|
||
func init() { | ||
tagWriteCmd.Flags().BoolVar(&deleteOtherTags, "delete-other-tags", false, "Delete tags not specified in the command") | ||
tagCmd.AddCommand(tagWriteCmd) | ||
} | ||
|
||
func tagWrite(cmd *cobra.Command, args []string) error { | ||
service := utils.NormalizeService(args[0]) | ||
if err := validateService(service); err != nil { | ||
return fmt.Errorf("Failed to validate service: %w", err) | ||
} | ||
|
||
key := utils.NormalizeKey(args[1]) | ||
if err := validateKey(key); err != nil { | ||
return fmt.Errorf("Failed to validate key: %w", err) | ||
} | ||
|
||
tags := make(map[string]string, len(args)-2) | ||
for _, tagArg := range args[2:] { | ||
tagKey, tagValue, found := strings.Cut(tagArg, "=") | ||
if !found { | ||
return fmt.Errorf("Failed to parse tag %s: tag must be in the form key=value", tagArg) | ||
} | ||
if err := validateTag(tagKey, tagValue); err != nil { | ||
return fmt.Errorf("Failed to validate tag with key %s: %w", tagKey, err) | ||
} | ||
tags[tagKey] = tagValue | ||
} | ||
|
||
if analyticsEnabled && analyticsClient != nil { | ||
_ = analyticsClient.Enqueue(analytics.Track{ | ||
UserId: username, | ||
Event: "Ran Command", | ||
Properties: analytics.NewProperties(). | ||
Set("command", "tag write"). | ||
Set("chamber-version", chamberVersion). | ||
Set("service", service). | ||
Set("key", key). | ||
Set("backend", backend), | ||
}) | ||
} | ||
|
||
secretStore, err := getSecretStore(cmd.Context()) | ||
if err != nil { | ||
return fmt.Errorf("Failed to get secret store: %w", err) | ||
} | ||
|
||
secretId := store.SecretId{ | ||
Service: service, | ||
Key: key, | ||
} | ||
|
||
err = secretStore.WriteTags(cmd.Context(), secretId, tags, deleteOtherTags) | ||
if err != nil { | ||
return fmt.Errorf("Failed to write tags: %w", err) | ||
} | ||
|
||
if quiet { | ||
fmt.Fprintf(os.Stdout, "%s\n", tags) | ||
return nil | ||
} | ||
|
||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 2, '\t', 0) | ||
fmt.Fprintln(w, "Key\tValue") | ||
for k, v := range tags { | ||
fmt.Fprintf(w, "%s\t%s\n", k, v) | ||
} | ||
w.Flush() | ||
return 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,17 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
// tagCmd represents the tag command | ||
tagCmd = &cobra.Command{ | ||
Use: "tag <subcommand> ...", | ||
Short: "work with tags on secrets", | ||
} | ||
) | ||
|
||
func init() { | ||
RootCmd.AddCommand(tagCmd) | ||
} |
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
Oops, something went wrong.