From 25d29508abdf9110ee0a7d487bd4bc89d71521c1 Mon Sep 17 00:00:00 2001 From: RAGOT David <35502263+Dav-14@users.noreply.github.com> Date: Thu, 4 Jan 2024 16:32:50 +0100 Subject: [PATCH] feat: check membership version (#1095) Co-authored-by: David Ragot --- .../cmd/cloud/organizations/users/root.go | 25 +++++++++++++++++++ components/fctl/cmd/stack/roles/root.go | 25 +++++++++++++++++++ components/fctl/pkg/clients.go | 13 ++++++++++ components/fctl/pkg/command.go | 14 +++++++++-- 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/components/fctl/cmd/cloud/organizations/users/root.go b/components/fctl/cmd/cloud/organizations/users/root.go index 3a3dfd9cdd..b4c01e2248 100644 --- a/components/fctl/cmd/cloud/organizations/users/root.go +++ b/components/fctl/cmd/cloud/organizations/users/root.go @@ -1,14 +1,39 @@ package users import ( + "fmt" + fctl "github.com/formancehq/fctl/pkg" "github.com/spf13/cobra" + "golang.org/x/mod/semver" ) func NewCommand() *cobra.Command { return fctl.NewMembershipCommand("users", fctl.WithAliases("u"), fctl.WithShortDescription("Users management"), + fctl.WithRunE(func(cmd *cobra.Command, args []string) error { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return err + } + + apiClient, err := fctl.NewMembershipClient(cmd, cfg) + if err != nil { + return err + } + + version := fctl.MembershipServerInfo(cmd.Context(), apiClient) + if !semver.IsValid(version) { + return nil + } + + if semver.Compare(version, "v0.26.1") >= 0 { + return nil + } + + return fmt.Errorf("unsupported membership server version: %s", version) + }), fctl.WithChildCommands( NewListCommand(), NewShowCommand(), diff --git a/components/fctl/cmd/stack/roles/root.go b/components/fctl/cmd/stack/roles/root.go index d3becda48b..f3019862a8 100644 --- a/components/fctl/cmd/stack/roles/root.go +++ b/components/fctl/cmd/stack/roles/root.go @@ -1,14 +1,39 @@ package roles import ( + "fmt" + fctl "github.com/formancehq/fctl/pkg" "github.com/spf13/cobra" + "golang.org/x/mod/semver" ) func NewCommand() *cobra.Command { return fctl.NewMembershipCommand("roles", fctl.WithAliases("s"), fctl.WithShortDescription("Stack users management within an organization"), + fctl.WithRunE(func(cmd *cobra.Command, args []string) error { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return err + } + + apiClient, err := fctl.NewMembershipClient(cmd, cfg) + if err != nil { + return err + } + + version := fctl.MembershipServerInfo(cmd.Context(), apiClient) + if !semver.IsValid(version) { + return nil + } + + if semver.Compare(version, "v0.26.1") >= 0 { + return nil + } + + return fmt.Errorf("unsupported membership server version: %s", version) + }), fctl.WithChildCommands( NewUpsertCommand(), NewListCommand(), diff --git a/components/fctl/pkg/clients.go b/components/fctl/pkg/clients.go index 0e8201fc8e..41b362326b 100644 --- a/components/fctl/pkg/clients.go +++ b/components/fctl/pkg/clients.go @@ -1,6 +1,7 @@ package fctl import ( + "context" "fmt" "github.com/formancehq/fctl/membershipclient" @@ -33,6 +34,18 @@ func NewMembershipClient(cmd *cobra.Command, cfg *Config) (*membershipclient.API return membershipclient.NewAPIClient(configuration), nil } +func MembershipServerInfo(ctx context.Context, client *membershipclient.APIClient) string { + serverInfo, response, err := client.DefaultApi.GetServerInfo(ctx).Execute() + if err != nil { + return fmt.Sprintf("Error: %s", err) + } + if response.StatusCode != 200 { + return fmt.Sprintf("Error: %s", response.Status) + } + return serverInfo.Version +} + + func NewStackClient(cmd *cobra.Command, cfg *Config, stack *membershipclient.Stack) (*formance.Formance, error) { profile := GetCurrentProfile(cmd, cfg) httpClient := GetHttpClient(cmd, map[string][]string{}) diff --git a/components/fctl/pkg/command.go b/components/fctl/pkg/command.go index 27f547ef84..7695aaf648 100644 --- a/components/fctl/pkg/command.go +++ b/components/fctl/pkg/command.go @@ -207,8 +207,6 @@ func WithStringArrayFlag(name string, defaultValue []string, help string) Comman } } - - func WithHiddenFlag(name string) CommandOptionFn { return func(cmd *cobra.Command) { _ = cmd.Flags().MarkHidden(name) @@ -248,6 +246,18 @@ func WithDeprecated(message string) CommandOptionFn { func WithController[T any](c Controller[T]) CommandOptionFn { return func(cmd *cobra.Command) { cmd.RunE = func(cmd *cobra.Command, args []string) error { + // Run all parent commands + parent := cmd.Parent() + for parent != nil { + if parent.RunE != nil { + err := parent.RunE(parent, args) + if err != nil { + return err + } + } + parent = parent.Parent() + } + renderable, err := c.Run(cmd, args) // If the controller return an argument error, we want to print the usage