-
Notifications
You must be signed in to change notification settings - Fork 42
fix(server): switch to flag for service account email #1429
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
base: main
Are you sure you want to change the base?
Changes from all commits
2263784
3319a45
04f4341
a135d2a
2b92a4d
c744d08
6db01c6
f570437
065b536
7eef125
f9740c6
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -20,9 +20,11 @@ import ( | |||||
| ) | ||||||
|
|
||||||
| const ( | ||||||
| serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" | ||||||
| serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 | ||||||
|
|
||||||
| serverIdFlag = "server-id" | ||||||
|
|
||||||
| serviceAccFlag = "service-account-email" | ||||||
| ) | ||||||
|
|
||||||
| type inputModel struct { | ||||||
|
|
@@ -33,14 +35,14 @@ type inputModel struct { | |||||
|
|
||||||
| func NewCmd(params *types.CmdParams) *cobra.Command { | ||||||
| cmd := &cobra.Command{ | ||||||
| Use: fmt.Sprintf("attach %s", serviceAccMailArg), | ||||||
| Use: "attach", | ||||||
| Short: "Attach a service account to a server", | ||||||
| Long: "Attach a service account to a server", | ||||||
| Args: args.SingleArg(serviceAccMailArg, nil), | ||||||
| Args: args.SingleOptionalArg(serviceAccMailArg, nil), | ||||||
| Example: examples.Build( | ||||||
| examples.NewExample( | ||||||
| `Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy"`, | ||||||
| "$ stackit server service-account attach xxx@sa.stackit.cloud --server-id yyy", | ||||||
| "$ stackit server service-account attach --service-account-email xxx@sa.stackit.cloud --server-id yyy", | ||||||
| ), | ||||||
| ), | ||||||
| RunE: func(cmd *cobra.Command, args []string) error { | ||||||
|
|
@@ -85,18 +87,27 @@ func NewCmd(params *types.CmdParams) *cobra.Command { | |||||
|
|
||||||
| func configureFlags(cmd *cobra.Command) { | ||||||
| cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") | ||||||
|
|
||||||
| cmd.Flags().VarP(flags.EmailFlag(), serviceAccFlag, "a", "Service Account Email") | ||||||
| err := flags.MarkFlagsRequired(cmd, serverIdFlag) | ||||||
| cobra.CheckErr(err) | ||||||
| } | ||||||
|
|
||||||
| func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { | ||||||
| serviceAccMail := inputArgs[0] | ||||||
| globalFlags := globalflags.Parse(p, cmd) | ||||||
| if globalFlags.ProjectId == "" { | ||||||
| return nil, &errors.ProjectIdError{} | ||||||
| } | ||||||
|
|
||||||
| var serviceAccMail string | ||||||
| if cmd.Flags().Changed(serviceAccFlag) { | ||||||
| serviceAccMail = flags.FlagToStringValue(p, cmd, serviceAccFlag) | ||||||
| } else if len(inputArgs) > 0 { | ||||||
| serviceAccMail = inputArgs[0] | ||||||
| p.Warn("using a positional argument for the service account email is deprecated and will be removed after 2026-12. Please use '--%s' instead.\n", serviceAccFlag) | ||||||
|
Member
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.
Suggested change
|
||||||
| } else { | ||||||
| return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) | ||||||
| } | ||||||
|
|
||||||
| model := inputModel{ | ||||||
| GlobalFlagModel: globalFlags, | ||||||
| ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -20,9 +20,11 @@ import ( | |||||
| ) | ||||||
|
|
||||||
| const ( | ||||||
| serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" | ||||||
| serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 | ||||||
|
Member
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.
Suggested change
Did you add this to our deprecation document? |
||||||
|
|
||||||
| serverIdFlag = "server-id" | ||||||
|
|
||||||
| serviceAccFlag = "service-account-email" | ||||||
| ) | ||||||
|
|
||||||
| type inputModel struct { | ||||||
|
|
@@ -33,14 +35,14 @@ type inputModel struct { | |||||
|
|
||||||
| func NewCmd(params *types.CmdParams) *cobra.Command { | ||||||
| cmd := &cobra.Command{ | ||||||
| Use: fmt.Sprintf("detach %s", serviceAccMailArg), | ||||||
| Use: "detach", | ||||||
| Short: "Detach a service account from a server", | ||||||
| Long: "Detach a service account from a server", | ||||||
| Args: args.SingleArg(serviceAccMailArg, nil), | ||||||
| Args: args.SingleOptionalArg(serviceAccMailArg, nil), | ||||||
| Example: examples.Build( | ||||||
| examples.NewExample( | ||||||
| `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, | ||||||
| "$ stackit server service-account detach xxx@sa.stackit.cloud --server-id yyy", | ||||||
| "$ stackit server service-account detach --service-account-email xxx@sa.stackit.cloud --server-id yyy", | ||||||
| ), | ||||||
| ), | ||||||
| RunE: func(cmd *cobra.Command, args []string) error { | ||||||
|
|
@@ -85,18 +87,27 @@ func NewCmd(params *types.CmdParams) *cobra.Command { | |||||
|
|
||||||
| func configureFlags(cmd *cobra.Command) { | ||||||
| cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server id") | ||||||
|
|
||||||
| cmd.Flags().VarP(flags.EmailFlag(), serviceAccFlag, "a", "Service Account Email") | ||||||
| err := flags.MarkFlagsRequired(cmd, serverIdFlag) | ||||||
| cobra.CheckErr(err) | ||||||
| } | ||||||
|
|
||||||
| func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) { | ||||||
| serviceAccMail := inputArgs[0] | ||||||
| globalFlags := globalflags.Parse(p, cmd) | ||||||
| if globalFlags.ProjectId == "" { | ||||||
| return nil, &errors.ProjectIdError{} | ||||||
| } | ||||||
|
|
||||||
| var serviceAccMail string | ||||||
| if cmd.Flags().Changed(serviceAccFlag) { | ||||||
| serviceAccMail = flags.FlagToStringValue(p, cmd, serviceAccFlag) | ||||||
| } else if len(inputArgs) > 0 { | ||||||
| serviceAccMail = inputArgs[0] | ||||||
| p.Warn("using a positional argument for the service account email is deprecated and will be removed after 2026-12. Please use '--%s' instead.\n", serviceAccFlag) | ||||||
|
Member
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.
Suggested change
|
||||||
| } else { | ||||||
| return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) | ||||||
| } | ||||||
|
|
||||||
| model := inputModel{ | ||||||
| GlobalFlagModel: globalFlags, | ||||||
| ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package flags | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "strings" | ||
|
|
||
| "github.com/spf13/pflag" | ||
| ) | ||
|
|
||
| type emailFlag struct { | ||
| value string | ||
| } | ||
|
|
||
| // Ensure the implementation satisfies the expected interface | ||
| var _ pflag.Value = &emailFlag{} | ||
|
|
||
| // EmailFlag returns a flag which must be a valid Email. | ||
| func EmailFlag() *emailFlag { | ||
| return &emailFlag{} | ||
| } | ||
|
|
||
| func (f *emailFlag) String() string { | ||
| return f.value | ||
| } | ||
|
|
||
| func (f *emailFlag) Set(value string) error { | ||
| isEmail := value != "" && strings.Contains(value, "@") | ||
| if !isEmail { | ||
| return fmt.Errorf("invalid email address: %s", value) | ||
| } | ||
| f.value = value | ||
| return nil | ||
| } | ||
|
|
||
| func (f *emailFlag) Type() string { | ||
| return "string" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package flags | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| func TestEmailFlag(t *testing.T) { | ||
| tests := []struct { | ||
| description string | ||
| value string | ||
| isValid bool | ||
| }{ | ||
| { | ||
| description: "valid", | ||
| value: "test@test", | ||
| isValid: true, | ||
| }, | ||
| { | ||
| description: "empty", | ||
| value: "", | ||
| isValid: false, | ||
| }, | ||
| { | ||
| description: "invalid", | ||
| value: "invalid-email", | ||
| isValid: false, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.description, func(t *testing.T) { | ||
| flag := EmailFlag() | ||
| cmd := &cobra.Command{ | ||
| Use: "test", | ||
| RunE: func(_ *cobra.Command, _ []string) error { | ||
| return nil | ||
| }, | ||
| } | ||
| cmd.Flags().Var(flag, "test-flag", "test") | ||
|
|
||
| err := cmd.Flags().Set("test-flag", tt.value) | ||
|
|
||
| if !tt.isValid && err == nil { | ||
| t.Fatalf("did not fail on invalid input") | ||
| } | ||
| if !tt.isValid { | ||
| return | ||
| } | ||
|
|
||
| if err != nil { | ||
| t.Fatalf("failed on valid input: %v", err) | ||
| } | ||
| value := FlagToStringValue(nil, cmd, "test-flag") | ||
| if value != tt.value { | ||
| t.Fatalf("flag did not return set value") | ||
| } | ||
| }) | ||
| } | ||
| } |
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.