From ed90c1bebcc1913d3729567883a5d3419af5390a Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 12:45:48 +0200 Subject: [PATCH 01/15] fix(server): switched to flag for service account email --- .../server/service-account/attach/attach.go | 26 +++++++++++++++---- .../server/service-account/detach/detach.go | 26 +++++++++++++++---- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index e9166c801..18cb59d9a 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -3,6 +3,7 @@ package attach import ( "context" "fmt" + "strings" "github.com/stackitcloud/stackit-cli/internal/pkg/types" @@ -23,6 +24,8 @@ const ( serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" serverIdFlag = "server-id" + + serviceAccFlag = "service-account-email" ) type inputModel struct { @@ -33,14 +36,14 @@ type inputModel struct { func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ - Use: fmt.Sprintf("attach %s", serviceAccMailArg), + Use: fmt.Sprintf("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), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2027-01 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 +88,31 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") - + cmd.Flags().StringP(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 in 2027-01. Please use '--%s' instead.\n", serviceAccFlag) + } else { + return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or as a positional argument`, serviceAccFlag) + } + + if serviceAccMail == "" || !strings.Contains(serviceAccMail, "@") { + return nil, fmt.Errorf("invalid service account email format: %q", serviceAccMail) + } + model := inputModel{ GlobalFlagModel: globalFlags, ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 671a7a883..6de4599fe 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -3,6 +3,7 @@ package detach import ( "context" "fmt" + "strings" "github.com/stackitcloud/stackit-cli/internal/pkg/types" @@ -23,6 +24,8 @@ const ( serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" serverIdFlag = "server-id" + + serviceAccFlag = "service-account-email" ) type inputModel struct { @@ -33,14 +36,14 @@ type inputModel struct { func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ - Use: fmt.Sprintf("detach %s", serviceAccMailArg), + Use: fmt.Sprintf("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), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2027-01 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 +88,31 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server id") - + cmd.Flags().StringP(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 in 2027-01. Please use '--%s' instead.\n", serviceAccFlag) + } else { + return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or as a positional argument`, serviceAccFlag) + } + + if serviceAccMail == "" || !strings.Contains(serviceAccMail, "@") { + return nil, fmt.Errorf("invalid service account email format: %q", serviceAccMail) + } + model := inputModel{ GlobalFlagModel: globalFlags, ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), From 32278ab861b7ab6a572ac4ccf3eaf9e8fd12fd6c Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 16:01:30 +0200 Subject: [PATCH 02/15] fix(server): adapted warning after jf to indicate deprecation --- internal/cmd/server/service-account/attach/attach.go | 2 +- internal/cmd/server/service-account/detach/detach.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 18cb59d9a..064375a2b 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -106,7 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu serviceAccMail = inputArgs[0] p.Warn("using a positional argument for the service account email is deprecated and will be removed in 2027-01. Please use '--%s' instead.\n", serviceAccFlag) } else { - return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or as a positional argument`, serviceAccFlag) + return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } if serviceAccMail == "" || !strings.Contains(serviceAccMail, "@") { diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 6de4599fe..cc97d2009 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -106,7 +106,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu serviceAccMail = inputArgs[0] p.Warn("using a positional argument for the service account email is deprecated and will be removed in 2027-01. Please use '--%s' instead.\n", serviceAccFlag) } else { - return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or as a positional argument`, serviceAccFlag) + return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } if serviceAccMail == "" || !strings.Contains(serviceAccMail, "@") { From 3bebbf117965dcd48d0f3612194bfa79af1fb697 Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 16:40:01 +0200 Subject: [PATCH 03/15] fix(server): moved email validation into flags package for reusability --- .../server/service-account/attach/attach.go | 2 +- .../server/service-account/detach/detach.go | 2 +- internal/pkg/flags/email.go | 37 +++++++++++ internal/pkg/flags/email_test.go | 61 +++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 internal/pkg/flags/email.go create mode 100644 internal/pkg/flags/email_test.go diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 064375a2b..6d3a84827 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -88,7 +88,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server ID") - cmd.Flags().StringP(serviceAccFlag, "a", "", "Service Account Email") + cmd.Flags().VarP(flags.EmailFlag(), serviceAccFlag, "a", "Service Account Email") err := flags.MarkFlagsRequired(cmd, serverIdFlag) cobra.CheckErr(err) } diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index cc97d2009..6f398569e 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -88,7 +88,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().VarP(flags.UUIDFlag(), serverIdFlag, "s", "Server id") - cmd.Flags().StringP(serviceAccFlag, "a", "", "Service Account Email") + cmd.Flags().VarP(flags.EmailFlag(), serviceAccFlag, "a", "Service Account Email") err := flags.MarkFlagsRequired(cmd, serverIdFlag) cobra.CheckErr(err) } diff --git a/internal/pkg/flags/email.go b/internal/pkg/flags/email.go new file mode 100644 index 000000000..203ea42a9 --- /dev/null +++ b/internal/pkg/flags/email.go @@ -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" +} diff --git a/internal/pkg/flags/email_test.go b/internal/pkg/flags/email_test.go new file mode 100644 index 000000000..e0a4def63 --- /dev/null +++ b/internal/pkg/flags/email_test.go @@ -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-uuid", + 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") + } + }) + } +} From 44f6c8966a8d5734eb7f733d3d130d4889c295c9 Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 17:24:45 +0200 Subject: [PATCH 04/15] fix(server): specified deprecation period --- internal/cmd/server/service-account/attach/attach.go | 4 ++-- internal/cmd/server/service-account/detach/detach.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 6d3a84827..627f9df91 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -21,7 +21,7 @@ import ( ) const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 serverIdFlag = "server-id" @@ -39,7 +39,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { Use: fmt.Sprintf("attach"), Short: "Attach a service account to a server", Long: "Attach a service account to a server", - Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2027-01 + Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 Example: examples.Build( examples.NewExample( `Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy"`, diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 6f398569e..506f18cdf 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -21,7 +21,7 @@ import ( ) const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 serverIdFlag = "server-id" @@ -39,7 +39,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { Use: fmt.Sprintf("detach"), Short: "Detach a service account from a server", Long: "Detach a service account from a server", - Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2027-01 + Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 Example: examples.Build( examples.NewExample( `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, From 32412503a913dd131e2cc04ff45cc4acc4430192 Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 17:26:47 +0200 Subject: [PATCH 05/15] fix(server): generated docs --- docs/stackit_server_service-account_attach.md | 9 +++++---- docs/stackit_server_service-account_detach.md | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/stackit_server_service-account_attach.md b/docs/stackit_server_service-account_attach.md index 0cf08c386..2cd7be4c7 100644 --- a/docs/stackit_server_service-account_attach.md +++ b/docs/stackit_server_service-account_attach.md @@ -7,21 +7,22 @@ Attach a service account to a server Attach a service account to a server ``` -stackit server service-account attach SERVICE_ACCOUNT_EMAIL [flags] +stackit server service-account attach [flags] ``` ### Examples ``` 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 ``` ### Options ``` - -h, --help Help for "stackit server service-account attach" - -s, --server-id string Server ID + -h, --help Help for "stackit server service-account attach" + -s, --server-id string Server ID + -a, --service-account-email string Service Account Email ``` ### Options inherited from parent commands diff --git a/docs/stackit_server_service-account_detach.md b/docs/stackit_server_service-account_detach.md index 87806ced3..6155054fb 100644 --- a/docs/stackit_server_service-account_detach.md +++ b/docs/stackit_server_service-account_detach.md @@ -7,21 +7,22 @@ Detach a service account from a server Detach a service account from a server ``` -stackit server service-account detach SERVICE_ACCOUNT_EMAIL [flags] +stackit server service-account detach [flags] ``` ### Examples ``` 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 ``` ### Options ``` - -h, --help Help for "stackit server service-account detach" - -s, --server-id string Server id + -h, --help Help for "stackit server service-account detach" + -s, --server-id string Server id + -a, --service-account-email string Service Account Email ``` ### Options inherited from parent commands From b608a1f7cb1be6f562fcca3d197b0875c637184f Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 17:31:44 +0200 Subject: [PATCH 06/15] fix(server): adapted deprecation period in warning --- internal/cmd/server/service-account/attach/attach.go | 2 +- internal/cmd/server/service-account/detach/detach.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 627f9df91..4ad0279f4 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu 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 in 2027-01. Please use '--%s' instead.\n", serviceAccFlag) + p.Warn("using a positional argument for the service account email is deprecated and will be removed on 2026-12-03. Please use '--%s' instead.\n", serviceAccFlag) } else { return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 506f18cdf..2613c519b 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu 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 in 2027-01. Please use '--%s' instead.\n", serviceAccFlag) + p.Warn("using a positional argument for the service account email is deprecated and will be removed on 2026-12-03. Please use '--%s' instead.\n", serviceAccFlag) } else { return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } From aa06167fcfffa210567b290a91199bec37773132 Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 17:37:07 +0200 Subject: [PATCH 07/15] fix(server): make linter happy --- internal/cmd/server/service-account/attach/attach.go | 2 +- internal/cmd/server/service-account/detach/detach.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 4ad0279f4..c4501c06d 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -36,7 +36,7 @@ type inputModel struct { func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ - Use: fmt.Sprintf("attach"), + Use: "attach", Short: "Attach a service account to a server", Long: "Attach a service account to a server", Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 2613c519b..39bfe5634 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -36,7 +36,7 @@ type inputModel struct { func NewCmd(params *types.CmdParams) *cobra.Command { cmd := &cobra.Command{ - Use: fmt.Sprintf("detach"), + Use: "detach", Short: "Detach a service account from a server", Long: "Detach a service account from a server", Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 From 4bbd8d0c5059d678cd5d7e44b0d0674cf7fc5752 Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 3 Jun 2026 18:21:10 +0200 Subject: [PATCH 08/15] fix(server): fix copy paste error --- internal/pkg/flags/email_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/flags/email_test.go b/internal/pkg/flags/email_test.go index e0a4def63..24af1f7c5 100644 --- a/internal/pkg/flags/email_test.go +++ b/internal/pkg/flags/email_test.go @@ -24,7 +24,7 @@ func TestEmailFlag(t *testing.T) { }, { description: "invalid", - value: "invalid-uuid", + value: "invalid-email", isValid: false, }, } From 15c04e5644532becf1de340614bfac8ff71c5200 Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 10 Jun 2026 10:41:26 +0200 Subject: [PATCH 09/15] chore(load-balancer): remove day from deprecation period --- internal/cmd/server/service-account/attach/attach.go | 6 +++--- internal/cmd/server/service-account/detach/detach.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index c4501c06d..ec3ae4141 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -21,7 +21,7 @@ import ( ) const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 serverIdFlag = "server-id" @@ -39,7 +39,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { Use: "attach", Short: "Attach a service account to a server", Long: "Attach a service account to a server", - Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 + Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 Example: examples.Build( examples.NewExample( `Attach a service account with mail "xxx@sa.stackit.cloud" to a server with ID "yyy"`, @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu 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 on 2026-12-03. Please use '--%s' instead.\n", serviceAccFlag) + 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) } else { return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 39bfe5634..e09d97bed 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -21,7 +21,7 @@ import ( ) const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 serverIdFlag = "server-id" @@ -39,7 +39,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { Use: "detach", Short: "Detach a service account from a server", Long: "Detach a service account from a server", - Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed 2026-12-03 + Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 Example: examples.Build( examples.NewExample( `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, @@ -104,7 +104,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu 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 on 2026-12-03. Please use '--%s' instead.\n", serviceAccFlag) + 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) } else { return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } From b54f2c0fd0893456f8112da8120da18687ec9dc9 Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 10 Jun 2026 10:44:29 +0200 Subject: [PATCH 10/15] chore(load-balancer): remove redundant email validation --- internal/cmd/server/service-account/attach/attach.go | 5 ----- internal/cmd/server/service-account/detach/detach.go | 5 ----- 2 files changed, 10 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index ec3ae4141..9f40adcb5 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -3,7 +3,6 @@ package attach import ( "context" "fmt" - "strings" "github.com/stackitcloud/stackit-cli/internal/pkg/types" @@ -109,10 +108,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } - if serviceAccMail == "" || !strings.Contains(serviceAccMail, "@") { - return nil, fmt.Errorf("invalid service account email format: %q", serviceAccMail) - } - model := inputModel{ GlobalFlagModel: globalFlags, ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index e09d97bed..e2c493bf7 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -3,7 +3,6 @@ package detach import ( "context" "fmt" - "strings" "github.com/stackitcloud/stackit-cli/internal/pkg/types" @@ -109,10 +108,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } - if serviceAccMail == "" || !strings.Contains(serviceAccMail, "@") { - return nil, fmt.Errorf("invalid service account email format: %q", serviceAccMail) - } - model := inputModel{ GlobalFlagModel: globalFlags, ServerId: flags.FlagToStringValue(p, cmd, serverIdFlag), From 549ce8e251cf7d536a5211afa4f8ba542f32af4e Mon Sep 17 00:00:00 2001 From: Jan Obernberger Date: Wed, 10 Jun 2026 10:48:20 +0200 Subject: [PATCH 11/15] chore(load-balancer): remove redundant deprecation comment --- internal/cmd/server/service-account/attach/attach.go | 2 +- internal/cmd/server/service-account/detach/detach.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 9f40adcb5..bc5044be3 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -38,7 +38,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { Use: "attach", Short: "Attach a service account to a server", Long: "Attach a service account to a server", - Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 + 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"`, diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index e2c493bf7..3138a8799 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -38,7 +38,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { Use: "detach", Short: "Detach a service account from a server", Long: "Detach a service account from a server", - Args: args.SingleOptionalArg(serviceAccMailArg, nil), // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 + Args: args.SingleOptionalArg(serviceAccMailArg, nil), Example: examples.Build( examples.NewExample( `Detach a service account with mail "xxx@sa.stackit.cloud" from a server "yyy"`, From 698baa2e612646c7308994e662cd38c84836f2db Mon Sep 17 00:00:00 2001 From: Jan Obernberger <52105660+j1n-o9r@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:18:45 +0200 Subject: [PATCH 12/15] Update internal/cmd/server/service-account/detach/detach.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ruben Hönle --- internal/cmd/server/service-account/detach/detach.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 3138a8799..54476f973 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -20,7 +20,7 @@ import ( ) const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12-31 serverIdFlag = "server-id" From 855d66b7f3fd4cca2cf029e3017623c76c76a98d Mon Sep 17 00:00:00 2001 From: Jan Obernberger <52105660+j1n-o9r@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:18:59 +0200 Subject: [PATCH 13/15] Update internal/cmd/server/service-account/detach/detach.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ruben Hönle --- internal/cmd/server/service-account/detach/detach.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/server/service-account/detach/detach.go b/internal/cmd/server/service-account/detach/detach.go index 54476f973..fcbb5f489 100644 --- a/internal/cmd/server/service-account/detach/detach.go +++ b/internal/cmd/server/service-account/detach/detach.go @@ -103,7 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu 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) + p.Warn("Using a positional argument for the service account email is deprecated and will be removed after 2026-12-31. Please use the '--%s' flag instead.\n", serviceAccFlag) } else { return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) } From 4fc930d8108811f873f8eb25ec6b38adadf4d157 Mon Sep 17 00:00:00 2001 From: Jan Obernberger <52105660+j1n-o9r@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:19:08 +0200 Subject: [PATCH 14/15] Update internal/cmd/server/service-account/attach/attach.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ruben Hönle --- internal/cmd/server/service-account/attach/attach.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index bc5044be3..959a395b0 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -20,7 +20,7 @@ import ( ) const ( - serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12 + serviceAccMailArg = "SERVICE_ACCOUNT_EMAIL" // Deprecated: positional argument is not used anymore, use the flag instead, will be removed after 2026-12-31 serverIdFlag = "server-id" From 7b18e6e2488a8d555dce4f53779798ae56ff3012 Mon Sep 17 00:00:00 2001 From: Jan Obernberger <52105660+j1n-o9r@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:19:16 +0200 Subject: [PATCH 15/15] Update internal/cmd/server/service-account/attach/attach.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ruben Hönle --- internal/cmd/server/service-account/attach/attach.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/server/service-account/attach/attach.go b/internal/cmd/server/service-account/attach/attach.go index 959a395b0..b32ff05ee 100644 --- a/internal/cmd/server/service-account/attach/attach.go +++ b/internal/cmd/server/service-account/attach/attach.go @@ -103,7 +103,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu 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) + p.Warn("Using a positional argument for the service account email is deprecated and will be removed after 2026-12. Please use the '--%s' flag instead.\n", serviceAccFlag) } else { return nil, fmt.Errorf(`service account must be specified by using either the --%s flag or (deprecated) as a positional argument`, serviceAccFlag) }