-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(cmd/influx): add secret cli #16786
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/influxdata/influxdb" | ||
"github.com/influxdata/influxdb/http" | ||
"github.com/spf13/cobra" | ||
input "github.com/tcnksm/go-input" | ||
) | ||
|
||
type secretSVCsFn func() (influxdb.SecretService, influxdb.OrganizationService, func(*input.UI) string, error) | ||
|
||
func cmdSecret(opts ...genericCLIOptFn) *cobra.Command { | ||
return newCmdSecretBuilder(newSecretSVCs, opts...).cmd() | ||
} | ||
|
||
type cmdSecretBuilder struct { | ||
genericCLIOpts | ||
|
||
svcFn secretSVCsFn | ||
|
||
key string | ||
org organization | ||
} | ||
|
||
func newCmdSecretBuilder(svcsFn secretSVCsFn, opts ...genericCLIOptFn) *cmdSecretBuilder { | ||
opt := genericCLIOpts{ | ||
in: os.Stdin, | ||
w: os.Stdout, | ||
} | ||
for _, o := range opts { | ||
o(&opt) | ||
} | ||
|
||
return &cmdSecretBuilder{ | ||
genericCLIOpts: opt, | ||
svcFn: svcsFn, | ||
} | ||
} | ||
|
||
func (b *cmdSecretBuilder) cmd() *cobra.Command { | ||
cmd := b.newCmd("secret", nil) | ||
cmd.Short = "Secret management commands" | ||
cmd.Run = seeHelp | ||
cmd.AddCommand( | ||
b.cmdDelete(), | ||
b.cmdFind(), | ||
b.cmdUpdate(), | ||
) | ||
return cmd | ||
} | ||
|
||
func (b *cmdSecretBuilder) cmdUpdate() *cobra.Command { | ||
cmd := b.newCmd("update", b.cmdUpdateRunEFn) | ||
cmd.Short = "Update secret" | ||
cmd.Flags().StringVarP(&b.key, "key", "k", "", "The secret key (required)") | ||
cmd.MarkFlagRequired("key") | ||
b.org.register(cmd, false) | ||
|
||
return cmd | ||
} | ||
|
||
func (b *cmdSecretBuilder) cmdDelete() *cobra.Command { | ||
cmd := b.newCmd("delete", b.cmdDeleteRunEFn) | ||
cmd.Short = "Delete secret" | ||
|
||
cmd.Flags().StringVarP(&b.key, "key", "k", "", "The secret key (required)") | ||
cmd.MarkFlagRequired("key") | ||
b.org.register(cmd, false) | ||
|
||
return cmd | ||
} | ||
|
||
func (b *cmdSecretBuilder) cmdUpdateRunEFn(cmd *cobra.Command, args []string) error { | ||
scrSVC, orgSVC, getSecretFn, err := b.svcFn() | ||
if err != nil { | ||
return err | ||
} | ||
orgID, err := b.org.getID(orgSVC) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ctx := context.Background() | ||
|
||
ui := &input.UI{ | ||
Writer: b.genericCLIOpts.w, | ||
Reader: b.genericCLIOpts.in, | ||
} | ||
secret := getSecretFn(ui) | ||
|
||
if err := scrSVC.PatchSecrets(ctx, orgID, map[string]string{b.key: secret}); err != nil { | ||
return fmt.Errorf("failed to update secret with key %q: %v", b.key, err) | ||
} | ||
|
||
w := b.newTabWriter() | ||
w.WriteHeaders("Key", "OrgID", "Updated") | ||
w.Write(map[string]interface{}{ | ||
"Key": b.key, | ||
"OrgID": orgID, | ||
"Updated": true, | ||
}) | ||
w.Flush() | ||
|
||
return nil | ||
} | ||
|
||
func (b *cmdSecretBuilder) cmdDeleteRunEFn(cmd *cobra.Command, args []string) error { | ||
scrSVC, orgSVC, _, err := b.svcFn() | ||
if err != nil { | ||
return err | ||
} | ||
orgID, err := b.org.getID(orgSVC) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ctx := context.Background() | ||
if err := scrSVC.DeleteSecret(ctx, orgID, b.key); err != nil { | ||
return fmt.Errorf("failed to delete secret with key %q: %v", b.key, err) | ||
} | ||
|
||
w := b.newTabWriter() | ||
w.WriteHeaders("Key", "OrgID", "Deleted") | ||
w.Write(map[string]interface{}{ | ||
"Key": b.key, | ||
"OrgID": orgID, | ||
"Deleted": true, | ||
}) | ||
w.Flush() | ||
|
||
return nil | ||
} | ||
|
||
func (b *cmdSecretBuilder) cmdFind() *cobra.Command { | ||
cmd := b.newCmd("find", b.cmdFindRunEFn) | ||
cmd.Short = "Find secrets" | ||
b.org.register(cmd, false) | ||
Comment on lines
+139
to
+141
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an overall critique of "find"/"list" commands throughout the My personal preference would be to make everything consistent and use either @jademcgough There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sanderson, this x1000! I've had the same feelings towards list|find. I would really love to see it become list if it does not allow for filtering. We do have filtering on some Find commands, either by name or what not. But these are still akin to list operations for me in most nix envs. I would love to see There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sanderson we're going to make these changes 👍. @influxdata/tools-team is on board 🤘 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
return cmd | ||
} | ||
|
||
func (b *cmdSecretBuilder) cmdFindRunEFn(cmd *cobra.Command, args []string) error { | ||
|
||
scrSVC, orgSVC, _, err := b.svcFn() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
orgID, err := b.org.getID(orgSVC) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
secrets, err := scrSVC.GetSecretKeys(context.Background(), orgID) | ||
if err != nil { | ||
return fmt.Errorf("failed to retrieve secret keys: %s", err) | ||
kelwang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
w := b.newTabWriter() | ||
w.WriteHeaders("Key", "OrganizationID") | ||
for _, s := range secrets { | ||
w.Write(map[string]interface{}{ | ||
"Key": s, | ||
"OrganizationID": orgID, | ||
}) | ||
} | ||
w.Flush() | ||
|
||
return nil | ||
} | ||
|
||
func newSecretSVCs() (influxdb.SecretService, influxdb.OrganizationService, func(*input.UI) string, error) { | ||
httpClient, err := newHTTPClient() | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
orgSvc := &http.OrganizationService{Client: httpClient} | ||
|
||
return &http.SecretService{Client: httpClient}, orgSvc, getSecret, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can pass a key, but how do you update the value of the secret?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sanderson This is done through a prompt similar to our password flow. I'm adding a card to provide it over the CLI as an arg in the same command.