From bd49464fa34ba6e534b31e7f3426c3c6e0b0ad4b Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Mon, 15 Aug 2022 17:21:00 +0700 Subject: [PATCH 01/16] feat: handler error when load config cli --- cmd/action.go | 39 ++++++++--------- cmd/client.go | 12 +++-- cmd/cmd.go | 73 ++++++++++++++++++++++++------- cmd/config.go | 97 +++++++++++++++++++++++++++++++++++++++++ cmd/errors.go | 30 +++++++++++++ cmd/group.go | 40 ++++++++--------- cmd/help.go | 22 ++++++++++ cmd/migrations.go | 39 ----------------- cmd/namespace.go | 40 ++++++++--------- cmd/organization.go | 65 ++++++++++++--------------- cmd/policy.go | 42 ++++++++---------- cmd/project.go | 42 ++++++++---------- cmd/role.go | 42 ++++++++---------- cmd/serve.go | 14 +----- cmd/server.go | 104 ++++++++++++++++++++++++++++++++++++++++++++ cmd/user.go | 40 ++++++++--------- cmd/utils.go | 56 ++++++++++++++++++++++++ config/config.go | 7 ++- main.go | 11 ++--- 19 files changed, 542 insertions(+), 273 deletions(-) create mode 100644 cmd/config.go create mode 100644 cmd/errors.go create mode 100644 cmd/help.go delete mode 100644 cmd/migrations.go create mode 100644 cmd/server.go diff --git a/cmd/action.go b/cmd/action.go index 8bc640083..93c725703 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "os" - "strconv" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func ActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func ActionCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "action", Aliases: []string{"actions"}, @@ -33,15 +30,17 @@ func ActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { }, } - cmd.AddCommand(createActionCommand(logger, appConfig)) - cmd.AddCommand(editActionCommand(logger, appConfig)) - cmd.AddCommand(viewActionCommand(logger, appConfig)) - cmd.AddCommand(listActionCommand(logger, appConfig)) + cmd.AddCommand(createActionCommand(cliConfig)) + cmd.AddCommand(editActionCommand(cliConfig)) + cmd.AddCommand(viewActionCommand(cliConfig)) + cmd.AddCommand(listActionCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createActionCommand(cliConfig *Config) *cli.Command { var filePath, header string cmd := &cli.Command{ @@ -68,9 +67,8 @@ func createActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Comma return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -86,7 +84,7 @@ func createActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Comma } spinner.Stop() - logger.Info(fmt.Sprintf("successfully created action %s with id %s", res.GetAction().GetName(), res.GetAction().GetId())) + fmt.Printf("successfully created action %s with id %s\n", res.GetAction().GetName(), res.GetAction().GetId()) return nil }, } @@ -99,7 +97,7 @@ func createActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Comma return cmd } -func editActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editActionCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -126,9 +124,8 @@ func editActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -144,7 +141,7 @@ func editActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command } spinner.Stop() - logger.Info(fmt.Sprintf("successfully edited action with id %s", actionID)) + fmt.Printf("successfully edited action with id %s\n", actionID) return nil }, } @@ -155,7 +152,7 @@ func editActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func viewActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewActionCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "view", Short: "View an action", @@ -170,9 +167,8 @@ func viewActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -207,7 +203,7 @@ func viewActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func listActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listActionCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all actions", @@ -222,9 +218,8 @@ func listActionCommand(logger log.Logger, appConfig *config.Shield) *cli.Command spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/client.go b/cmd/client.go index 43970a17f..cf6777174 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -5,20 +5,26 @@ import ( "time" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" + "github.com/spf13/cobra" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) func createConnection(ctx context.Context, host string) (*grpc.ClientConn, error) { opts := []grpc.DialOption{ - grpc.WithInsecure(), + grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock(), } return grpc.DialContext(ctx, host, opts...) } -func createClient(ctx context.Context, host string) (shieldv1beta1.ShieldServiceClient, func(), error) { - dialTimeoutCtx, dialCancel := context.WithTimeout(ctx, time.Second*2) +func createClient(cmd *cobra.Command) (shieldv1beta1.ShieldServiceClient, func(), error) { + dialTimeoutCtx, dialCancel := context.WithTimeout(cmd.Context(), time.Second*2) + host, err := cmd.Flags().GetString("host") + if err != nil { + return nil, nil, err + } conn, err := createConnection(dialTimeoutCtx, host) if err != nil { dialCancel() diff --git a/cmd/cmd.go b/cmd/cmd.go index b8e874d7b..4ac4daac0 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,27 +1,68 @@ package cmd import ( - "github.com/odpf/salt/log" - "github.com/odpf/shield/config" + "github.com/MakeNowJust/heredoc" + "github.com/odpf/salt/cmdx" + "github.com/spf13/cobra" cli "github.com/spf13/cobra" ) -func New(logger log.Logger, appConfig *config.Shield) *cli.Command { +func New(cfg *Config) *cli.Command { + cliConfig = cfg + var cmd = &cli.Command{ - Use: "shield", - SilenceUsage: true, + Use: "shield [flags]", + Short: "A cloud native role-based authorization aware reverse-proxy service", + Long: heredoc.Doc(` + A cloud native role-based authorization aware reverse-proxy service.`), + SilenceUsage: true, + SilenceErrors: true, + Example: heredoc.Doc(` + $ shield group list + $ shield organization list + $ shield project list + $ shield user create --file user.yaml + `), + Annotations: map[string]string{ + "group:core": "true", + "help:learn": heredoc.Doc(` + Use 'shield --help' for more information about a command. + Read the manual at https://odpf.github.io/shield/ + `), + "help:feedback": heredoc.Doc(` + Open an issue here https://github.com/odpf/shield/issues + `), + "help:environment": heredoc.Doc(` + See 'shield help environment' for the list of supported environment variables. + `), + }, + } + + cmd.PersistentPreRunE = func(subCmd *cobra.Command, args []string) error { + if IsClientCLI(subCmd) { + if !IsClientConfigHostExist(subCmd) { + return ErrClientConfigHostNotFound + } + } + return nil } - cmd.AddCommand(serveCommand(logger, appConfig)) - cmd.AddCommand(migrationsCommand(logger, appConfig)) - cmd.AddCommand(migrationsRollbackCommand(logger, appConfig)) - cmd.AddCommand(NamespaceCommand(logger, appConfig)) - cmd.AddCommand(UserCommand(logger, appConfig)) - cmd.AddCommand(OrganizationCommand(logger, appConfig)) - cmd.AddCommand(GroupCommand(logger, appConfig)) - cmd.AddCommand(ProjectCommand(logger, appConfig)) - cmd.AddCommand(RoleCommand(logger, appConfig)) - cmd.AddCommand(ActionCommand(logger, appConfig)) - cmd.AddCommand(PolicyCommand(logger, appConfig)) + cmd.AddCommand(ServerCommand()) + cmd.AddCommand(NamespaceCommand(cliConfig)) + cmd.AddCommand(UserCommand(cliConfig)) + cmd.AddCommand(OrganizationCommand(cliConfig)) + cmd.AddCommand(GroupCommand(cliConfig)) + cmd.AddCommand(ProjectCommand(cliConfig)) + cmd.AddCommand(RoleCommand(cliConfig)) + cmd.AddCommand(ActionCommand(cliConfig)) + cmd.AddCommand(PolicyCommand(cliConfig)) + cmd.AddCommand(configCommand()) + + // Help topics + cmdx.SetHelp(cmd) + cmd.AddCommand(cmdx.SetCompletionCmd("shield")) + cmd.AddCommand(cmdx.SetHelpTopic("environment", envHelp)) + cmd.AddCommand(cmdx.SetHelpTopic("auth", authHelp)) + cmd.AddCommand(cmdx.SetRefCmd(cmd)) return cmd } diff --git a/cmd/config.go b/cmd/config.go new file mode 100644 index 000000000..1d884c1e5 --- /dev/null +++ b/cmd/config.go @@ -0,0 +1,97 @@ +package cmd + +import ( + "fmt" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/salt/cmdx" + "github.com/spf13/cobra" +) + +var cliConfig *Config + +type Config struct { + Host string `mapstructure:"host"` +} + +func LoadConfig() (*Config, error) { + var config Config + + cfg := cmdx.SetConfig("shield") + err := cfg.Load(&config) + + return &config, err +} + +func configCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "config ", + Short: "Manage client configurations", + Example: heredoc.Doc(` + $ shield config init + $ shield config list`), + } + + cmd.AddCommand(configInitCommand()) + cmd.AddCommand(configListCommand()) + + return cmd +} + +func configInitCommand() *cobra.Command { + return &cobra.Command{ + Use: "init", + Short: "Initialize a new client configuration", + Example: heredoc.Doc(` + $ shield config init + `), + Annotations: map[string]string{ + "group:core": "true", + }, + RunE: func(cmd *cobra.Command, args []string) error { + cfg := cmdx.SetConfig("shield") + + if err := cfg.Init(&Config{}); err != nil { + return err + } + + fmt.Printf("config created: %v\n", cfg.File()) + return nil + }, + } +} + +func configListCommand() *cobra.Command { + var cmd = &cobra.Command{ + Use: "list", + Short: "List client configuration settings", + Example: heredoc.Doc(` + $ shield config list + `), + Annotations: map[string]string{ + "group:core": "true", + }, + RunE: func(cmd *cobra.Command, args []string) error { + cfg := cmdx.SetConfig("shield") + + data, err := cfg.Read() + if err != nil { + return ErrClientConfigNotFound + } + + fmt.Println(data) + return nil + }, + } + return cmd +} + +func bindFlagsFromClientConfig(cmd *cobra.Command) { + cmd.PersistentFlags().StringP("host", "H", "", "Shield API service to connect to") + + if cliConfig != nil { + if cliConfig.Host != "" { + cmd.PersistentFlags().Set("host", cliConfig.Host) + } + } +} diff --git a/cmd/errors.go b/cmd/errors.go new file mode 100644 index 000000000..a84a5583d --- /dev/null +++ b/cmd/errors.go @@ -0,0 +1,30 @@ +package cmd + +import ( + "errors" + + "github.com/MakeNowJust/heredoc" +) + +var ( + ErrClientConfigNotFound = errors.New(heredoc.Doc(` + Shield client config not found. + + Run "shield config init" or + Run "shield help environment" for more information. + `)) + ErrClientConfigHostNotFound = errors.New(heredoc.Doc(` + Shield client config "host" not found. + + Pass shield server host with "--host" flag or + use shield config. + + Run "shield config " or + "shield help environment" for more information. + `)) + ErrClientNotAuthorized = errors.New(heredoc.Doc(` + Shield auth error. Shield requires an auth header. + + Run "shield help auth" for more information. + `)) +) diff --git a/cmd/group.go b/cmd/group.go index 5f8689ee4..1a20b560e 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "os" - "strconv" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func GroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func GroupCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "group", Aliases: []string{"groups"}, @@ -30,18 +27,21 @@ func GroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { `), Annotations: map[string]string{ "group:core": "true", + "client": "true", }, } - cmd.AddCommand(createGroupCommand(logger, appConfig)) - cmd.AddCommand(editGroupCommand(logger, appConfig)) - cmd.AddCommand(viewGroupCommand(logger, appConfig)) - cmd.AddCommand(listGroupCommand(logger, appConfig)) + cmd.AddCommand(createGroupCommand(cliConfig)) + cmd.AddCommand(editGroupCommand(cliConfig)) + cmd.AddCommand(viewGroupCommand(cliConfig)) + cmd.AddCommand(listGroupCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createGroupCommand(cliConfig *Config) *cli.Command { var filePath, header string cmd := &cli.Command{ @@ -68,9 +68,8 @@ func createGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -86,7 +85,7 @@ func createGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman } spinner.Stop() - logger.Info(fmt.Sprintf("successfully created group %s with id %s", res.GetGroup().GetName(), res.GetGroup().GetId())) + fmt.Printf("successfully created group %s with id %s\n", res.GetGroup().GetName(), res.GetGroup().GetId()) return nil }, } @@ -99,7 +98,7 @@ func createGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman return cmd } -func editGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editGroupCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -126,9 +125,8 @@ func editGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -144,7 +142,7 @@ func editGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command } spinner.Stop() - logger.Info(fmt.Sprintf("successfully edited group with id %s", groupID)) + fmt.Printf("successfully edited group with id %s\n", groupID) return nil }, } @@ -155,7 +153,7 @@ func editGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func viewGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewGroupCommand(cliConfig *Config) *cli.Command { var metadata bool cmd := &cli.Command{ @@ -172,9 +170,8 @@ func viewGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -229,7 +226,7 @@ func viewGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func listGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listGroupCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all groups", @@ -244,9 +241,8 @@ func listGroupCommand(logger log.Logger, appConfig *config.Shield) *cli.Command spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/help.go b/cmd/help.go new file mode 100644 index 000000000..79081eab7 --- /dev/null +++ b/cmd/help.go @@ -0,0 +1,22 @@ +package cmd + +import "github.com/MakeNowJust/heredoc" + +var envHelp = map[string]string{ + "short": "Environment variables that can be used with shield", + "long": heredoc.Doc(` + ODPF_CONFIG_DIR: the directory where shield will store configuration files. Default: + "$XDG_CONFIG_HOME/odpf" or "$HOME/.config/odpf". + NO_COLOR: set to any value to avoid printing ANSI escape sequences for color output. + CLICOLOR: set to "0" to disable printing ANSI colors in output. + `), +} + +var authHelp = map[string]string{ + "short": "Auth configs that need to be used with shield", + "long": heredoc.Doc(` + Send an additional flag header with "key:value" format. + Example: + shield create user -f user.yaml -h X-Shield-Email:user@odpf.io + `), +} diff --git a/cmd/migrations.go b/cmd/migrations.go deleted file mode 100644 index a09abb17d..000000000 --- a/cmd/migrations.go +++ /dev/null @@ -1,39 +0,0 @@ -package cmd - -import ( - "github.com/odpf/salt/log" - "github.com/odpf/shield/config" - "github.com/odpf/shield/internal/store/postgres/migrations" - "github.com/odpf/shield/pkg/db" - cli "github.com/spf13/cobra" -) - -func migrationsCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { - c := &cli.Command{ - Use: "migrate", - Short: "Run DB Schema Migrations", - Example: "shield migrate", - RunE: func(c *cli.Command, args []string) error { - return db.RunMigrations(db.Config{ - Driver: appConfig.DB.Driver, - URL: appConfig.DB.URL, - }, migrations.MigrationFs, migrations.ResourcePath) - }, - } - return c -} - -func migrationsRollbackCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { - c := &cli.Command{ - Use: "migration-rollback", - Short: "Run DB Schema Migrations Rollback to last state", - Example: "shield migration-rollback", - RunE: func(c *cli.Command, args []string) error { - return db.RunRollback(db.Config{ - Driver: appConfig.DB.Driver, - URL: appConfig.DB.URL, - }, migrations.MigrationFs, migrations.ResourcePath) - }, - } - return c -} diff --git a/cmd/namespace.go b/cmd/namespace.go index 6fac70f2c..ab30f9b68 100644 --- a/cmd/namespace.go +++ b/cmd/namespace.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "os" - "strconv" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func NamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func NamespaceCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "namespace", Aliases: []string{"namespaces"}, @@ -30,18 +27,21 @@ func NamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Command `), Annotations: map[string]string{ "group:core": "true", + "client": "true", }, } - cmd.AddCommand(createNamespaceCommand(logger, appConfig)) - cmd.AddCommand(editNamespaceCommand(logger, appConfig)) - cmd.AddCommand(viewNamespaceCommand(logger, appConfig)) - cmd.AddCommand(listNamespaceCommand(logger, appConfig)) + cmd.AddCommand(createNamespaceCommand(cliConfig)) + cmd.AddCommand(editNamespaceCommand(cliConfig)) + cmd.AddCommand(viewNamespaceCommand(cliConfig)) + cmd.AddCommand(listNamespaceCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createNamespaceCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -68,9 +68,8 @@ func createNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Co return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -84,7 +83,7 @@ func createNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Co } spinner.Stop() - logger.Info(fmt.Sprintf("successfully created namespace %s with id %s", res.GetNamespace().GetName(), res.GetNamespace().GetId())) + fmt.Printf("successfully created namespace %s with id %s\n", res.GetNamespace().GetName(), res.GetNamespace().GetId()) return nil }, } @@ -95,7 +94,7 @@ func createNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Co return cmd } -func editNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editNamespaceCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -122,9 +121,8 @@ func editNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -140,7 +138,7 @@ func editNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm } spinner.Stop() - logger.Info(fmt.Sprintf("successfully edited namespace with id %s to id %s and name %s", namespaceID, res.GetNamespace().GetId(), res.GetNamespace().GetName())) + fmt.Printf("successfully edited namespace with id %s to id %s and name %s\n", namespaceID, res.GetNamespace().GetId(), res.GetNamespace().GetName()) return nil }, } @@ -151,7 +149,7 @@ func editNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm return cmd } -func viewNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewNamespaceCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "view", Short: "View a namespace", @@ -166,9 +164,8 @@ func viewNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -206,7 +203,7 @@ func viewNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm return cmd } -func listNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listNamespaceCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all namespaces", @@ -221,9 +218,8 @@ func listNamespaceCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/organization.go b/cmd/organization.go index 40d07cf16..92dbc8170 100644 --- a/cmd/organization.go +++ b/cmd/organization.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "os" - "strconv" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func OrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func OrganizationCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "organization", Aliases: []string{"organizations"}, @@ -30,21 +27,24 @@ func OrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Comma `), Annotations: map[string]string{ "group:core": "true", + "client": "true", }, } - cmd.AddCommand(createOrganizationCommand(logger, appConfig)) - cmd.AddCommand(editOrganizationCommand(logger, appConfig)) - cmd.AddCommand(viewOrganizationCommand(logger, appConfig)) - cmd.AddCommand(listOrganizationCommand(logger, appConfig)) - cmd.AddCommand(admaddOrganizationCommand(logger, appConfig)) - cmd.AddCommand(admremoveOrganizationCommand(logger, appConfig)) - cmd.AddCommand(admlistOrganizationCommand(logger, appConfig)) + cmd.AddCommand(createOrganizationCommand(cliConfig)) + cmd.AddCommand(editOrganizationCommand(cliConfig)) + cmd.AddCommand(viewOrganizationCommand(cliConfig)) + cmd.AddCommand(listOrganizationCommand(cliConfig)) + cmd.AddCommand(admaddOrganizationCommand(cliConfig)) + cmd.AddCommand(admremoveOrganizationCommand(cliConfig)) + cmd.AddCommand(admlistOrganizationCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createOrganizationCommand(cliConfig *Config) *cli.Command { var filePath, header string cmd := &cli.Command{ @@ -71,9 +71,8 @@ func createOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -89,7 +88,7 @@ func createOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli } spinner.Stop() - logger.Info(fmt.Sprintf("successfully created organization %s with id %s", res.GetOrganization().GetName(), res.GetOrganization().GetId())) + fmt.Printf("successfully created organization %s with id %s\n", res.GetOrganization().GetName(), res.GetOrganization().GetId()) return nil }, } @@ -102,7 +101,7 @@ func createOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli return cmd } -func editOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editOrganizationCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -129,9 +128,8 @@ func editOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.C return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -147,7 +145,7 @@ func editOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.C } spinner.Stop() - logger.Info(fmt.Sprintf("successfully edited organization with id %s", organizationID)) + fmt.Printf("successfully edited organization with id %s\n", organizationID) return nil }, } @@ -158,7 +156,7 @@ func editOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.C return cmd } -func viewOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewOrganizationCommand(cliConfig *Config) *cli.Command { var metadata bool cmd := &cli.Command{ @@ -175,9 +173,8 @@ func viewOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.C spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -231,7 +228,7 @@ func viewOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.C return cmd } -func listOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listOrganizationCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all organizations", @@ -246,9 +243,8 @@ func listOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.C spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -288,7 +284,7 @@ func listOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.C return cmd } -func admaddOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func admaddOrganizationCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -315,9 +311,8 @@ func admaddOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -333,7 +328,7 @@ func admaddOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli } spinner.Stop() - logger.Info("successfully added admin(s) to organization") + fmt.Println("successfully added admin(s) to organization") return nil }, } @@ -344,7 +339,7 @@ func admaddOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli return cmd } -func admremoveOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func admremoveOrganizationCommand(cliConfig *Config) *cli.Command { var userID string cmd := &cli.Command{ @@ -361,9 +356,8 @@ func admremoveOrganizationCommand(logger log.Logger, appConfig *config.Shield) * spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -379,7 +373,7 @@ func admremoveOrganizationCommand(logger log.Logger, appConfig *config.Shield) * } spinner.Stop() - logger.Info("successfully removed admin from organization") + fmt.Println("successfully removed admin from organization") return nil }, } @@ -390,7 +384,7 @@ func admremoveOrganizationCommand(logger log.Logger, appConfig *config.Shield) * return cmd } -func admlistOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func admlistOrganizationCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "admlist", Short: "list admins of an organization", @@ -405,9 +399,8 @@ func admlistOrganizationCommand(logger log.Logger, appConfig *config.Shield) *cl spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/policy.go b/cmd/policy.go index 5cc055c50..3d386b472 100644 --- a/cmd/policy.go +++ b/cmd/policy.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "os" - "strconv" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func PolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func PolicyCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "policy", Aliases: []string{"policies"}, @@ -29,19 +26,22 @@ func PolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { $ shield policy list `), Annotations: map[string]string{ - "policy:core": "true", + "group:core": "true", + "client": "true", }, } - cmd.AddCommand(createPolicyCommand(logger, appConfig)) - cmd.AddCommand(editPolicyCommand(logger, appConfig)) - cmd.AddCommand(viewPolicyCommand(logger, appConfig)) - cmd.AddCommand(listPolicyCommand(logger, appConfig)) + cmd.AddCommand(createPolicyCommand(cliConfig)) + cmd.AddCommand(editPolicyCommand(cliConfig)) + cmd.AddCommand(viewPolicyCommand(cliConfig)) + cmd.AddCommand(listPolicyCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createPolicyCommand(cliConfig *Config) *cli.Command { var filePath, header string cmd := &cli.Command{ @@ -68,9 +68,8 @@ func createPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Comma return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -86,7 +85,7 @@ func createPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Comma } spinner.Stop() - logger.Info("successfully created policy") + fmt.Println("successfully created policy") return nil }, } @@ -99,7 +98,7 @@ func createPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Comma return cmd } -func editPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editPolicyCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -126,9 +125,8 @@ func editPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -144,7 +142,7 @@ func editPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command } spinner.Stop() - logger.Info("successfully edited policy") + fmt.Println("successfully edited policy") return nil }, } @@ -155,7 +153,7 @@ func editPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func viewPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewPolicyCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "view", Short: "View a policy", @@ -170,9 +168,8 @@ func viewPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -207,7 +204,7 @@ func viewPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func listPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listPolicyCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all policies", @@ -222,9 +219,8 @@ func listPolicyCommand(logger log.Logger, appConfig *config.Shield) *cli.Command spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/project.go b/cmd/project.go index 6e7dfb15a..c9befaf1f 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "os" - "strconv" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func ProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func ProjectCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "project", Aliases: []string{"projects"}, @@ -29,19 +26,22 @@ func ProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { $ shield project list `), Annotations: map[string]string{ - "project:core": "true", + "group:core": "true", + "client": "true", }, } - cmd.AddCommand(createProjectCommand(logger, appConfig)) - cmd.AddCommand(editProjectCommand(logger, appConfig)) - cmd.AddCommand(viewProjectCommand(logger, appConfig)) - cmd.AddCommand(listProjectCommand(logger, appConfig)) + cmd.AddCommand(createProjectCommand(cliConfig)) + cmd.AddCommand(editProjectCommand(cliConfig)) + cmd.AddCommand(viewProjectCommand(cliConfig)) + cmd.AddCommand(listProjectCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createProjectCommand(cliConfig *Config) *cli.Command { var filePath, header string cmd := &cli.Command{ @@ -68,9 +68,8 @@ func createProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -86,7 +85,7 @@ func createProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm } spinner.Stop() - logger.Info(fmt.Sprintf("successfully created project %s with id %s", res.GetProject().GetName(), res.GetProject().GetId())) + fmt.Printf("successfully created project %s with id %s\n", res.GetProject().GetName(), res.GetProject().GetId()) return nil }, } @@ -99,7 +98,7 @@ func createProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comm return cmd } -func editProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editProjectCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -126,9 +125,8 @@ func editProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -144,7 +142,7 @@ func editProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman } spinner.Stop() - logger.Info(fmt.Sprintf("successfully edited project with id %s", projectID)) + fmt.Printf("successfully edited project with id %s\n", projectID) return nil }, } @@ -155,7 +153,7 @@ func editProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman return cmd } -func viewProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewProjectCommand(cliConfig *Config) *cli.Command { var metadata bool cmd := &cli.Command{ @@ -172,9 +170,8 @@ func viewProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -229,7 +226,7 @@ func viewProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman return cmd } -func listProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listProjectCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all projects", @@ -244,9 +241,8 @@ func listProjectCommand(logger log.Logger, appConfig *config.Shield) *cli.Comman spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/role.go b/cmd/role.go index 80291c788..c2ac6e0e7 100644 --- a/cmd/role.go +++ b/cmd/role.go @@ -4,18 +4,15 @@ import ( "context" "fmt" "os" - "strconv" "strings" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func RoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func RoleCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "role", Aliases: []string{"roles"}, @@ -30,19 +27,22 @@ func RoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { $ shield role list `), Annotations: map[string]string{ - "role:core": "true", + "group:core": "true", + "client": "true", }, } - cmd.AddCommand(createRoleCommand(logger, appConfig)) - cmd.AddCommand(editRoleCommand(logger, appConfig)) - cmd.AddCommand(viewRoleCommand(logger, appConfig)) - cmd.AddCommand(listRoleCommand(logger, appConfig)) + cmd.AddCommand(createRoleCommand(cliConfig)) + cmd.AddCommand(editRoleCommand(cliConfig)) + cmd.AddCommand(viewRoleCommand(cliConfig)) + cmd.AddCommand(listRoleCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createRoleCommand(cliConfig *Config) *cli.Command { var filePath, header string cmd := &cli.Command{ @@ -69,9 +69,8 @@ func createRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -87,7 +86,7 @@ func createRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command } spinner.Stop() - logger.Info(fmt.Sprintf("successfully created role %s with id %s", res.GetRole().GetName(), res.GetRole().GetId())) + fmt.Printf("successfully created role %s with id %s\n", res.GetRole().GetName(), res.GetRole().GetId()) return nil }, } @@ -100,7 +99,7 @@ func createRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func editRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editRoleCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -127,9 +126,8 @@ func editRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -145,7 +143,7 @@ func editRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { } spinner.Stop() - logger.Info(fmt.Sprintf("successfully edited role with id %s", roleID)) + fmt.Printf("successfully edited role with id %s\n", roleID) return nil }, } @@ -156,7 +154,7 @@ func editRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { return cmd } -func viewRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewRoleCommand(cliConfig *Config) *cli.Command { var metadata bool cmd := &cli.Command{ @@ -173,9 +171,8 @@ func viewRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -230,7 +227,7 @@ func viewRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { return cmd } -func listRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listRoleCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all roles", @@ -245,9 +242,8 @@ func listRoleCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/serve.go b/cmd/serve.go index adb9a2581..363823378 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -9,6 +9,7 @@ import ( "syscall" "time" + _ "github.com/authzed/authzed-go/proto/authzed/api/v0" _ "github.com/jackc/pgx/v4/stdlib" newrelic "github.com/newrelic/go-agent" "github.com/odpf/shield/core/action" @@ -34,25 +35,12 @@ import ( "github.com/odpf/salt/log" salt_server "github.com/odpf/salt/server" "github.com/pkg/profile" - cli "github.com/spf13/cobra" ) var ( ruleCacheRefreshDelay = time.Minute * 2 ) -func serveCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { - c := &cli.Command{ - Use: "serve", - Short: "Start server and proxy default on port 8080", - Example: "shield serve", - RunE: func(cmd *cli.Command, args []string) error { - return serve(logger, appConfig) - }, - } - return c -} - func serve(logger log.Logger, cfg *config.Shield) error { if profiling := os.Getenv("SHIELD_PROFILE"); profiling == "true" || profiling == "1" { defer profile.Start(profile.CPUProfile, profile.ProfilePath("."), profile.NoShutdownHook).Stop() diff --git a/cmd/server.go b/cmd/server.go new file mode 100644 index 000000000..80c652cc7 --- /dev/null +++ b/cmd/server.go @@ -0,0 +1,104 @@ +package cmd + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/config" + "github.com/odpf/shield/internal/store/postgres/migrations" + "github.com/odpf/shield/pkg/db" + shieldlogger "github.com/odpf/shield/pkg/logger" + "github.com/spf13/cobra" + cli "github.com/spf13/cobra" +) + +func ServerCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "server ", + Aliases: []string{"s"}, + Short: "Server management", + Long: "Server management commands.", + Example: heredoc.Doc(` + $ shield server start + $ shield server start -c ./config.yaml + $ shield server migrate + $ shield server migrate -c ./config.yaml + $ shield server migrate-rollback + $ shield server migrate-rollback -c ./config.yaml + `), + } + + cmd.AddCommand(startCommand()) + cmd.AddCommand(migrateCommand()) + cmd.AddCommand(migrateRollbackCommand()) + + return cmd +} + +func startCommand() *cobra.Command { + var configFile string + + c := &cli.Command{ + Use: "start", + Short: "Start server and proxy default on port 8080", + Example: "shield server start", + RunE: func(cmd *cli.Command, args []string) error { + appConfig, err := config.Load(configFile) + if err != nil { + panic(err) + } + logger := shieldlogger.InitLogger(appConfig.Log) + + return serve(logger, appConfig) + }, + } + + c.Flags().StringVarP(&configFile, "config", "c", "./config.yaml", "Config file path") + return c +} + +func migrateCommand() *cobra.Command { + var configFile string + + c := &cli.Command{ + Use: "migrate", + Short: "Run DB Schema Migrations", + Example: "shield migrate", + RunE: func(c *cli.Command, args []string) error { + appConfig, err := config.Load(configFile) + if err != nil { + panic(err) + } + + return db.RunMigrations(db.Config{ + Driver: appConfig.DB.Driver, + URL: appConfig.DB.URL, + }, migrations.MigrationFs, migrations.ResourcePath) + }, + } + + c.Flags().StringVarP(&configFile, "config", "c", "./config.yaml", "Config file path") + return c +} + +func migrateRollbackCommand() *cobra.Command { + var configFile string + + c := &cli.Command{ + Use: "migration-rollback", + Short: "Run DB Schema Migrations Rollback to last state", + Example: "shield migration-rollback", + RunE: func(c *cli.Command, args []string) error { + appConfig, err := config.Load(configFile) + if err != nil { + panic(err) + } + + return db.RunRollback(db.Config{ + Driver: appConfig.DB.Driver, + URL: appConfig.DB.URL, + }, migrations.MigrationFs, migrations.ResourcePath) + }, + } + + c.Flags().StringVarP(&configFile, "config", "c", "./config.yaml", "Config file path") + return c +} diff --git a/cmd/user.go b/cmd/user.go index d15d32c85..8ed807bbb 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "os" - "strconv" "github.com/MakeNowJust/heredoc" - "github.com/odpf/salt/log" "github.com/odpf/salt/printer" - "github.com/odpf/shield/config" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) -func UserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func UserCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "user", Aliases: []string{"users"}, @@ -30,18 +27,21 @@ func UserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { `), Annotations: map[string]string{ "group:core": "true", + "client": "true", }, } - cmd.AddCommand(createUserCommand(logger, appConfig)) - cmd.AddCommand(editUserCommand(logger, appConfig)) - cmd.AddCommand(viewUserCommand(logger, appConfig)) - cmd.AddCommand(listUserCommand(logger, appConfig)) + cmd.AddCommand(createUserCommand(cliConfig)) + cmd.AddCommand(editUserCommand(cliConfig)) + cmd.AddCommand(viewUserCommand(cliConfig)) + cmd.AddCommand(listUserCommand(cliConfig)) + + bindFlagsFromClientConfig(cmd) return cmd } -func createUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func createUserCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -68,9 +68,8 @@ func createUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -84,7 +83,7 @@ func createUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command } spinner.Stop() - logger.Info(fmt.Sprintf("successfully created user %s with id %s", res.GetUser().GetName(), res.GetUser().GetId())) + fmt.Printf("successfully created user %s with id %s\n", res.GetUser().GetName(), res.GetUser().GetId()) return nil }, } @@ -95,7 +94,7 @@ func createUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command return cmd } -func editUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func editUserCommand(cliConfig *Config) *cli.Command { var filePath string cmd := &cli.Command{ @@ -122,9 +121,8 @@ func editUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { return err } - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -140,7 +138,7 @@ func editUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { } spinner.Stop() - logger.Info(fmt.Sprintf("successfully edited user with id %s", userID)) + fmt.Printf("successfully edited user with id %s\n", userID) return nil }, } @@ -151,7 +149,7 @@ func editUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { return cmd } -func viewUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func viewUserCommand(cliConfig *Config) *cli.Command { var metadata bool cmd := &cli.Command{ @@ -168,9 +166,8 @@ func viewUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } @@ -219,7 +216,7 @@ func viewUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { return cmd } -func listUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { +func listUserCommand(cliConfig *Config) *cli.Command { cmd := &cli.Command{ Use: "list", Short: "List all users", @@ -234,9 +231,8 @@ func listUserCommand(logger log.Logger, appConfig *config.Shield) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - host := appConfig.App.Host + ":" + strconv.Itoa(appConfig.App.Port) ctx := context.Background() - client, cancel, err := createClient(ctx, host) + client, cancel, err := createClient(cmd) if err != nil { return err } diff --git a/cmd/utils.go b/cmd/utils.go index f6f4168d6..b2bcd42e7 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" + "github.com/spf13/cobra" "google.golang.org/grpc/metadata" "gopkg.in/yaml.v3" ) @@ -45,3 +46,58 @@ func setCtxHeader(ctx context.Context, header string) context.Context { return ctx } + +// func CheckAuth(args []string) bool { +// if md, ok := metadata.FromOutgoingContext(ctx); ok { +// return len(md) > 0 +// } +// return false +// } + +func IsAuthCheckEnabled(cmd *cobra.Command) bool { + switch cmd.Name() { + case "help", "config", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd: + return false + } + + for c := cmd; c.Parent() != nil; c = c.Parent() { + if c.Annotations != nil && c.Annotations["skipAuth"] == "true" { + return false + } + } + + return true +} + +func IsClientCLI(cmd *cobra.Command) bool { + for c := cmd; c.Parent() != nil; c = c.Parent() { + if c.Annotations != nil && c.Annotations["client"] == "true" { + return true + } + } + return false +} + +func IsClientConfigHostExist(cmd *cobra.Command) bool { + host, err := cmd.Flags().GetString("host") + fmt.Println(host) + if err != nil { + return false + } + if host != "" { + return true + } + return false +} + +func IsClientConfigHeaderExist(cmd *cobra.Command) bool { + host, err := cmd.Flags().GetString("header") + fmt.Println(host) + if err != nil { + return false + } + if host != "" { + return true + } + return false +} diff --git a/config/config.go b/config/config.go index 07ade0200..38470e7e2 100644 --- a/config/config.go +++ b/config/config.go @@ -30,7 +30,7 @@ type NewRelic struct { Enabled bool `yaml:"enabled" mapstructure:"enabled"` } -func Load() (*Shield, error) { +func Load(configfileFromFlag string) (*Shield, error) { conf := &Shield{} var options []config.LoaderOption @@ -48,6 +48,11 @@ func Load() (*Shield, error) { options = append(options, config.WithPath(filepath.Join(currentHomeDir, ".config"))) } + // override all config sources and prioritize one from file + if configfileFromFlag != "" { + options = []config.LoaderOption{config.WithFile(configfileFromFlag)} + } + l := config.NewLoader(options...) if err := l.Load(conf); err != nil { if errors.As(err, &config.ConfigFileNotFoundError{}) { diff --git a/main.go b/main.go index 6c221e927..a6b0d632f 100644 --- a/main.go +++ b/main.go @@ -4,22 +4,17 @@ import ( "fmt" "os" - shieldlogger "github.com/odpf/shield/pkg/logger" - "github.com/odpf/shield/cmd" - "github.com/odpf/shield/config" _ "github.com/authzed/authzed-go/proto/authzed/api/v0" ) func main() { - appConfig, err := config.Load() + cliConfig, err := cmd.LoadConfig() if err != nil { - panic(err) + cliConfig = &cmd.Config{} } - logger := shieldlogger.InitLogger(appConfig.Log) - - if err := cmd.New(logger, appConfig).Execute(); err != nil { + if err := cmd.New(cliConfig).Execute(); err != nil { fmt.Printf("%+v", err) os.Exit(1) } From 92e6d5b4a3a9857f4afdc5dd18aba40587077035 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Tue, 16 Aug 2022 12:21:40 +0700 Subject: [PATCH 02/16] feat(cli): add server init config --- .gitignore | 3 + cmd/action.go | 5 +- cmd/cmd.go | 4 +- cmd/group.go | 5 +- cmd/namespace.go | 5 +- cmd/organization.go | 7 +- cmd/policy.go | 5 +- cmd/project.go | 5 +- cmd/role.go | 5 +- cmd/server.go | 74 +++++++++++++-- cmd/user.go | 5 +- cmd/utils.go | 65 +------------- config/init.go | 163 ++++++++++++++++++++++++++++++++++ config/rules/sample.grpc.yaml | 3 +- go.mod | 1 - pkg/file/file.go | 44 +++++++++ 16 files changed, 308 insertions(+), 91 deletions(-) create mode 100644 config/init.go create mode 100644 pkg/file/file.go diff --git a/.gitignore b/.gitignore index f90fd7219..4195a26bf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build .env .DS_Store .idea/ +.vscode/ proxies/*.yaml proxies/*.yml .temp @@ -18,3 +19,5 @@ ignore/ vendor/ buf.lock buf.yaml +resources_config +rules \ No newline at end of file diff --git a/cmd/action.go b/cmd/action.go index 93c725703..aed8025a0 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -58,7 +59,7 @@ func createActionCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.ActionRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -115,7 +116,7 @@ func editActionCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.ActionRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/cmd.go b/cmd/cmd.go index 4ac4daac0..65c360b54 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -39,8 +39,8 @@ func New(cfg *Config) *cli.Command { } cmd.PersistentPreRunE = func(subCmd *cobra.Command, args []string) error { - if IsClientCLI(subCmd) { - if !IsClientConfigHostExist(subCmd) { + if isClientCLI(subCmd) { + if !clientConfigHostExist(subCmd) { return ErrClientConfigHostNotFound } } diff --git a/cmd/group.go b/cmd/group.go index 1a20b560e..228ef02ab 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -59,7 +60,7 @@ func createGroupCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.GroupRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -116,7 +117,7 @@ func editGroupCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.GroupRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/namespace.go b/cmd/namespace.go index ab30f9b68..c33684528 100644 --- a/cmd/namespace.go +++ b/cmd/namespace.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -59,7 +60,7 @@ func createNamespaceCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.NamespaceRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -112,7 +113,7 @@ func editNamespaceCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.NamespaceRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/organization.go b/cmd/organization.go index 92dbc8170..4c347a4c6 100644 --- a/cmd/organization.go +++ b/cmd/organization.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -62,7 +63,7 @@ func createOrganizationCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.OrganizationRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -119,7 +120,7 @@ func editOrganizationCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.OrganizationRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -302,7 +303,7 @@ func admaddOrganizationCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.AddOrganizationAdminRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/policy.go b/cmd/policy.go index 3d386b472..92b47eaf3 100644 --- a/cmd/policy.go +++ b/cmd/policy.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -59,7 +60,7 @@ func createPolicyCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.PolicyRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -116,7 +117,7 @@ func editPolicyCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.PolicyRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/project.go b/cmd/project.go index c9befaf1f..8e67c5f50 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -59,7 +60,7 @@ func createProjectCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.ProjectRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -116,7 +117,7 @@ func editProjectCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.ProjectRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/role.go b/cmd/role.go index c2ac6e0e7..c3303bd5b 100644 --- a/cmd/role.go +++ b/cmd/role.go @@ -8,6 +8,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -60,7 +61,7 @@ func createRoleCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.RoleRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -117,7 +118,7 @@ func editRoleCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.RoleRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/server.go b/cmd/server.go index 80c652cc7..8a0225ab5 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -1,6 +1,10 @@ package cmd import ( + "fmt" + "os" + "path" + "github.com/MakeNowJust/heredoc" "github.com/odpf/shield/config" "github.com/odpf/shield/internal/store/postgres/migrations" @@ -17,6 +21,7 @@ func ServerCommand() *cobra.Command { Short: "Server management", Long: "Server management commands.", Example: heredoc.Doc(` + $ shield server init $ shield server start $ shield server start -c ./config.yaml $ shield server migrate @@ -26,14 +31,71 @@ func ServerCommand() *cobra.Command { `), } - cmd.AddCommand(startCommand()) - cmd.AddCommand(migrateCommand()) - cmd.AddCommand(migrateRollbackCommand()) + cmd.AddCommand(serverInitCommand()) + cmd.AddCommand(serverStartCommand()) + cmd.AddCommand(serverMigrateCommand()) + cmd.AddCommand(serverMigrateRollbackCommand()) return cmd } -func startCommand() *cobra.Command { +func serverInitCommand() *cobra.Command { + var configFile string + var resourcesURL string + var rulesURL string + + c := &cli.Command{ + Use: "init", + Short: "Initialize server", + Long: heredoc.Doc(` + Initializing server. Creating a sample of shield server config. + Default: ./.shield.yaml + `), + Example: "shield server init", + RunE: func(cmd *cli.Command, args []string) error { + cwd, err := os.Getwd() + if err != nil { + return err + } + defaultResourcesURL := fmt.Sprintf("file://%s", path.Join(cwd, "resources_config")) + defaultRulesURL := fmt.Sprintf("file://%s", path.Join(cwd, "rules")) + + if resourcesURL == "" { + resourcesURL = defaultResourcesURL + } + if rulesURL == "" { + rulesURL = defaultRulesURL + } + + if err := config.Init(resourcesURL, rulesURL, configFile); err != nil { + return err + } + + fmt.Printf("config created: %v\n", configFile) + return nil + }, + } + + c.Flags().StringVarP(&configFile, "output", "o", "./.shield.yaml", "Output config file path") + c.Flags().StringVarP(&resourcesURL, "resources", "r", "", heredoc.Doc(` + URL path of resources. Full path prefixed with scheme where resources config yaml files are kept + e.g.: + local storage file "file:///tmp/resources_config" + GCS Bucket "gs://shield-bucket-example" + (default: file://{pwd}/resources_config) + `)) + c.Flags().StringVarP(&rulesURL, "rule", "u", "", heredoc.Doc(` + URL path of rules. Full path prefixed with scheme where ruleset yaml files are kept + e.g.: + local storage file "file:///tmp/rules" + GCS Bucket "gs://shield-bucket-example" + (default: file://{pwd}/rules) + `)) + + return c +} + +func serverStartCommand() *cobra.Command { var configFile string c := &cli.Command{ @@ -55,7 +117,7 @@ func startCommand() *cobra.Command { return c } -func migrateCommand() *cobra.Command { +func serverMigrateCommand() *cobra.Command { var configFile string c := &cli.Command{ @@ -79,7 +141,7 @@ func migrateCommand() *cobra.Command { return c } -func migrateRollbackCommand() *cobra.Command { +func serverMigrateRollbackCommand() *cobra.Command { var configFile string c := &cli.Command{ diff --git a/cmd/user.go b/cmd/user.go index 8ed807bbb..387096897 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/odpf/salt/printer" + "github.com/odpf/shield/pkg/file" shieldv1beta1 "github.com/odpf/shield/proto/v1beta1" cli "github.com/spf13/cobra" ) @@ -59,7 +60,7 @@ func createUserCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.UserRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } @@ -112,7 +113,7 @@ func editUserCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() var reqBody shieldv1beta1.UserRequestBody - if err := parseFile(filePath, &reqBody); err != nil { + if err := file.Parse(filePath, &reqBody); err != nil { return err } diff --git a/cmd/utils.go b/cmd/utils.go index b2bcd42e7..4ba55be4e 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -2,40 +2,13 @@ package cmd import ( "context" - "encoding/json" - "errors" "fmt" - "io/ioutil" - "path/filepath" "strings" "github.com/spf13/cobra" "google.golang.org/grpc/metadata" - "gopkg.in/yaml.v3" ) -func parseFile(filePath string, v interface{}) error { - b, err := ioutil.ReadFile(filePath) - if err != nil { - return err - } - - switch filepath.Ext(filePath) { - case ".json": - if err := json.Unmarshal(b, v); err != nil { - return fmt.Errorf("invalid json: %w", err) - } - case ".yaml", ".yml": - if err := yaml.Unmarshal(b, v); err != nil { - return fmt.Errorf("invalid yaml: %w", err) - } - default: - return errors.New("unsupported file type") - } - - return nil -} - func setCtxHeader(ctx context.Context, header string) context.Context { s := strings.Split(header, ":") key := s[0] @@ -47,29 +20,7 @@ func setCtxHeader(ctx context.Context, header string) context.Context { return ctx } -// func CheckAuth(args []string) bool { -// if md, ok := metadata.FromOutgoingContext(ctx); ok { -// return len(md) > 0 -// } -// return false -// } - -func IsAuthCheckEnabled(cmd *cobra.Command) bool { - switch cmd.Name() { - case "help", "config", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd: - return false - } - - for c := cmd; c.Parent() != nil; c = c.Parent() { - if c.Annotations != nil && c.Annotations["skipAuth"] == "true" { - return false - } - } - - return true -} - -func IsClientCLI(cmd *cobra.Command) bool { +func isClientCLI(cmd *cobra.Command) bool { for c := cmd; c.Parent() != nil; c = c.Parent() { if c.Annotations != nil && c.Annotations["client"] == "true" { return true @@ -78,7 +29,7 @@ func IsClientCLI(cmd *cobra.Command) bool { return false } -func IsClientConfigHostExist(cmd *cobra.Command) bool { +func clientConfigHostExist(cmd *cobra.Command) bool { host, err := cmd.Flags().GetString("host") fmt.Println(host) if err != nil { @@ -89,15 +40,3 @@ func IsClientConfigHostExist(cmd *cobra.Command) bool { } return false } - -func IsClientConfigHeaderExist(cmd *cobra.Command) bool { - host, err := cmd.Flags().GetString("header") - fmt.Println(host) - if err != nil { - return false - } - if host != "" { - return true - } - return false -} diff --git a/config/init.go b/config/init.go new file mode 100644 index 000000000..10cc9d4cf --- /dev/null +++ b/config/init.go @@ -0,0 +1,163 @@ +package config + +import ( + "embed" + "errors" + "io/ioutil" + "net/url" + "os" + "path" + "path/filepath" + "strings" + + _ "embed" + + "github.com/mcuadros/go-defaults" + "github.com/odpf/shield/internal/proxy" + "github.com/odpf/shield/pkg/file" + "gopkg.in/yaml.v2" +) + +//go:embed resources_config/* +var resourcesConfig embed.FS + +//go:embed rules/* +var rulesConfig embed.FS + +func Init(resourcesURL, rulesURL, configFile string) error { + if file.Exist(configFile) { + return errors.New("config file already exists") + } + + cfg := &Shield{} + + defaults.SetDefaults(cfg) + + if err := initResourcesPath(resourcesURL); err != nil { + return err + } + if err := initRulesPath(rulesURL); err != nil { + return err + } + + cfg.App.RulesPath = rulesURL + cfg.App.ResourcesConfigPath = resourcesURL + // sample proxy + cfg.Proxy = proxy.ServicesConfig{ + Services: []proxy.Config{ + { + Name: "base", + Host: "0.0.0.0", + Port: 5556, + RulesPath: rulesURL, + }, + }, + } + + data, err := yaml.Marshal(cfg) + if err != nil { + return err + } + + if _, err := os.Stat(configFile); os.IsNotExist(err) { + if !file.DirExists(configFile) { + _ = os.MkdirAll(filepath.Dir(configFile), 0755) + } + } + + if err := ioutil.WriteFile(configFile, data, 0655); err != nil { + return err + } + + return nil +} + +func initResourcesPath(resURL string) error { + resourceURL, err := url.Parse(resURL) + if err != nil { + return err + } + + if resourceURL.Scheme != "file" { + // skip creating + return nil + } + + resourcesPath := resourceURL.Path + if !file.DirExists(resourcesPath) { + _ = os.MkdirAll(resourcesPath, 0755) + } + + files, err := ioutil.ReadDir(resourcesPath) + if err != nil { + return err + } + + for _, f := range files { + if strings.HasSuffix(f.Name(), ".yaml") || strings.HasSuffix(f.Name(), ".yml") { + // skip creating + return nil + } + } + + resourceYaml, err := resourcesConfig.ReadFile("resources_config/resources.yaml") + if err != nil { + return err + } + + if err := ioutil.WriteFile(path.Join(resourcesPath, "resources.yaml"), resourceYaml, 0655); err != nil { + return err + } + + return nil +} + +func initRulesPath(rURL string) error { + rulesURL, err := url.Parse(rURL) + if err != nil { + return err + } + + if rulesURL.Scheme != "file" { + // skip creating + return nil + } + + rulesPath := rulesURL.Path + + if !file.DirExists(rulesPath) { + _ = os.MkdirAll(rulesPath, 0755) + } + + files, err := ioutil.ReadDir(rulesPath) + if err != nil { + return err + } + + for _, f := range files { + if strings.HasSuffix(f.Name(), ".yaml") || strings.HasSuffix(f.Name(), ".yml") { + // skip creating + return nil + } + } + + ruleRestYaml, err := rulesConfig.ReadFile("rules/sample.rest.yaml") + if err != nil { + return err + } + + if err := ioutil.WriteFile(path.Join(rulesPath, "sample.rest.yaml"), ruleRestYaml, 0655); err != nil { + return err + } + + ruleRestGrpc, err := resourcesConfig.ReadFile("rules/sample.grpc.yaml") + if err != nil { + return err + } + + if err := ioutil.WriteFile(path.Join(rulesPath, "sample.grpc.yaml"), ruleRestGrpc, 0655); err != nil { + return err + } + + return nil +} diff --git a/config/rules/sample.grpc.yaml b/config/rules/sample.grpc.yaml index 56b8ae4b2..9e734e3f0 100644 --- a/config/rules/sample.grpc.yaml +++ b/config/rules/sample.grpc.yaml @@ -1,6 +1,5 @@ rules: - - - frontend: + - frontend: url: "proto.v1.RuntimeService/" methods: ["POST"] backend: diff --git a/go.mod b/go.mod index f8ce74e8d..abaab40ed 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,6 @@ require ( google.golang.org/grpc v1.46.0 google.golang.org/protobuf v1.28.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b - gotest.tools v2.2.0+incompatible ) require ( diff --git a/pkg/file/file.go b/pkg/file/file.go new file mode 100644 index 000000000..bed11cae0 --- /dev/null +++ b/pkg/file/file.go @@ -0,0 +1,44 @@ +package file + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "gopkg.in/yaml.v2" +) + +func Exist(filename string) bool { + _, err := os.Stat(filename) + return err == nil +} + +func DirExists(path string) bool { + f, err := os.Stat(path) + return err == nil && f.IsDir() +} + +func Parse(filePath string, v interface{}) error { + b, err := ioutil.ReadFile(filePath) + if err != nil { + return err + } + + switch filepath.Ext(filePath) { + case ".json": + if err := json.Unmarshal(b, v); err != nil { + return fmt.Errorf("invalid json: %w", err) + } + case ".yaml", ".yml": + if err := yaml.Unmarshal(b, v); err != nil { + return fmt.Errorf("invalid yaml: %w", err) + } + default: + return errors.New("unsupported file type") + } + + return nil +} From 61a01569c5f7f88375025234ce3c1b6a1a62d733 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Tue, 16 Aug 2022 12:28:32 +0700 Subject: [PATCH 03/16] fix: lint --- cmd/client.go | 1 + core/namespace/namespace.go | 2 +- core/resource/resource.go | 4 +--- internal/store/postgres/policy_repository.go | 2 +- internal/store/postgres/role_repository.go | 2 +- pkg/body_extractor/grpc_payload.go | 9 +++++---- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cmd/client.go b/cmd/client.go index cf6777174..c0ff227c6 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -23,6 +23,7 @@ func createClient(cmd *cobra.Command) (shieldv1beta1.ShieldServiceClient, func() dialTimeoutCtx, dialCancel := context.WithTimeout(cmd.Context(), time.Second*2) host, err := cmd.Flags().GetString("host") if err != nil { + dialCancel() return nil, nil, err } conn, err := createConnection(dialTimeoutCtx, host) diff --git a/core/namespace/namespace.go b/core/namespace/namespace.go index 5c45e4e68..3a5881a4d 100644 --- a/core/namespace/namespace.go +++ b/core/namespace/namespace.go @@ -33,7 +33,7 @@ func IsSystemNamespaceID(nsID string) bool { return strListHas(systemIdsDefinition, nsID) } -//postgres://shield:@:5432/ +// postgres://shield:@:5432/ func CreateID(backend, resourceType string) string { return fmt.Sprintf("%s_%s", backend, resourceType) } diff --git a/core/resource/resource.go b/core/resource/resource.go index 63206c8ea..ac85ae11f 100644 --- a/core/resource/resource.go +++ b/core/resource/resource.go @@ -45,9 +45,7 @@ type Resource struct { UpdatedAt time.Time } -/* - /project/uuid/ -*/ +// /project/uuid/ func (res Resource) CreateURN() string { isSystemNS := namespace.IsSystemNamespaceID(res.NamespaceID) if isSystemNS { diff --git a/internal/store/postgres/policy_repository.go b/internal/store/postgres/policy_repository.go index 03c7fb27c..9f9dc07e8 100644 --- a/internal/store/postgres/policy_repository.go +++ b/internal/store/postgres/policy_repository.go @@ -119,7 +119,7 @@ func (r PolicyRepository) List(ctx context.Context) ([]policy.Policy, error) { return transformedPolicies, nil } -//TODO this is actually upsert +// TODO this is actually upsert func (r PolicyRepository) Create(ctx context.Context, pol policy.Policy) (string, error) { // TODO need to check actionID != "" diff --git a/internal/store/postgres/role_repository.go b/internal/store/postgres/role_repository.go index 8fba54368..6ac176ecf 100644 --- a/internal/store/postgres/role_repository.go +++ b/internal/store/postgres/role_repository.go @@ -69,7 +69,7 @@ func (r RoleRepository) Get(ctx context.Context, id string) (role.Role, error) { return transformedRole, nil } -//TODO this is actually an upsert +// TODO this is actually an upsert func (r RoleRepository) Create(ctx context.Context, rl role.Role) (string, error) { if rl.ID == "" { return "", role.ErrInvalidID diff --git a/pkg/body_extractor/grpc_payload.go b/pkg/body_extractor/grpc_payload.go index 89e77ddcb..c9818fd87 100644 --- a/pkg/body_extractor/grpc_payload.go +++ b/pkg/body_extractor/grpc_payload.go @@ -134,10 +134,11 @@ type grpcRequestParser struct { // format. The caller owns the returned msg memory. // // If there is an error, possible values are: -// * io.EOF, when no messages remain -// * io.ErrUnexpectedEOF -// * of type transport.ConnectionError -// * an error from the status package +// - io.EOF, when no messages remain +// - io.ErrUnexpectedEOF +// - of type transport.ConnectionError +// - an error from the status package +// // No other error values or types must be returned, which also means // that the underlying io.Reader must not return an incompatible // error. From eaa3776ec6b74bb3c41513b9db66bef06e20b2e1 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Tue, 16 Aug 2022 12:36:39 +0700 Subject: [PATCH 04/16] feat(proto): add support proton commit in makefile --- Makefile | 9 +++++++-- buf.gen.yaml | 1 - cmd/config.go | 2 +- cmd/errors.go | 4 ++-- cmd/utils.go | 2 -- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index a08ad8499..f548aa5f5 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2) .PHONY: build check fmt lint test test-race vet test-cover-html help install proto .DEFAULT_GOAL := build +PROTON_COMMIT := "1497165f2f48facb3ec6f5c5556ccd44f0a7119f" install: @echo "Clean up imports..." @@ -26,8 +27,12 @@ coverage: ## print code coverage clean : rm -rf dist -proto: - ./buf.gen.yaml && cp -R proto/odpf/shield/* proto/ && rm -Rf proto/odpf +proto: ## Generate the protobuf files + @echo " > generating protobuf from odpf/proton" + @echo " > [info] make sure correct version of dependencies are installed using 'make install'" + @buf generate https://github.com/odpf/proton/archive/${PROTON_COMMIT}.zip#strip_components=1 --template buf.gen.yaml --path odpf/shield + @cp -R proto/odpf/shield/* proto/ && rm -Rf proto/odpf + @echo " > protobuf compilation finished" help: @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/buf.gen.yaml b/buf.gen.yaml index 2a618baa6..ddf0fa1fc 100755 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,4 +1,3 @@ -#!/usr/bin/env -S buf generate buf.build/odpf/proton:1497165f2f48facb3ec6f5c5556ccd44f0a7119f --path odpf/shield --template --- version: "v1" plugins: diff --git a/cmd/config.go b/cmd/config.go index 1d884c1e5..5dc4de947 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -87,7 +87,7 @@ func configListCommand() *cobra.Command { } func bindFlagsFromClientConfig(cmd *cobra.Command) { - cmd.PersistentFlags().StringP("host", "H", "", "Shield API service to connect to") + cmd.PersistentFlags().StringP("host", "h", "", "Shield API service to connect to") if cliConfig != nil { if cliConfig.Host != "" { diff --git a/cmd/errors.go b/cmd/errors.go index a84a5583d..68fe6a993 100644 --- a/cmd/errors.go +++ b/cmd/errors.go @@ -10,14 +10,14 @@ var ( ErrClientConfigNotFound = errors.New(heredoc.Doc(` Shield client config not found. - Run "shield config init" or + Run "shield config init" to initialize a new client config or Run "shield help environment" for more information. `)) ErrClientConfigHostNotFound = errors.New(heredoc.Doc(` Shield client config "host" not found. Pass shield server host with "--host" flag or - use shield config. + set host in shield config. Run "shield config " or "shield help environment" for more information. diff --git a/cmd/utils.go b/cmd/utils.go index 4ba55be4e..44328ed36 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -2,7 +2,6 @@ package cmd import ( "context" - "fmt" "strings" "github.com/spf13/cobra" @@ -31,7 +30,6 @@ func isClientCLI(cmd *cobra.Command) bool { func clientConfigHostExist(cmd *cobra.Command) bool { host, err := cmd.Flags().GetString("host") - fmt.Println(host) if err != nil { return false } From 760f076c1c96de4a6a98f7409ba988d3f3905650 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Tue, 16 Aug 2022 13:08:27 +0700 Subject: [PATCH 05/16] fix: missing header in create user cli --- cmd/group.go | 4 +--- cmd/user.go | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/group.go b/cmd/group.go index 228ef02ab..0939eb163 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -76,9 +76,7 @@ func createGroupCommand(cliConfig *Config) *cli.Command { } defer cancel() - ctx = setCtxHeader(ctx, header) - - res, err := client.CreateGroup(ctx, &shieldv1beta1.CreateGroupRequest{ + res, err := client.CreateGroup(setCtxHeader(ctx, header), &shieldv1beta1.CreateGroupRequest{ Body: &reqBody, }) if err != nil { diff --git a/cmd/user.go b/cmd/user.go index 387096897..e7b800fd7 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -43,7 +43,7 @@ func UserCommand(cliConfig *Config) *cli.Command { } func createUserCommand(cliConfig *Config) *cli.Command { - var filePath string + var filePath, header string cmd := &cli.Command{ Use: "create", @@ -76,7 +76,7 @@ func createUserCommand(cliConfig *Config) *cli.Command { } defer cancel() - res, err := client.CreateUser(ctx, &shieldv1beta1.CreateUserRequest{ + res, err := client.CreateUser(setCtxHeader(ctx, header), &shieldv1beta1.CreateUserRequest{ Body: &reqBody, }) if err != nil { @@ -91,6 +91,8 @@ func createUserCommand(cliConfig *Config) *cli.Command { cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to the user body file") cmd.MarkFlagRequired("file") + cmd.Flags().StringVarP(&header, "header", "H", "", "Header :") + cmd.MarkFlagRequired("header") return cmd } From 0531f0bf50317964403c90addad04db0bb9da46f Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Tue, 16 Aug 2022 21:19:14 +0700 Subject: [PATCH 06/16] fix: refactor cmd utils --- cmd/action.go | 2 +- cmd/client.go | 20 ++++++++++++++++++++ cmd/context.go | 19 +++++++++++++++++++ cmd/{cmd.go => root.go} | 2 +- cmd/utils.go | 40 ---------------------------------------- 5 files changed, 41 insertions(+), 42 deletions(-) create mode 100644 cmd/context.go rename cmd/{cmd.go => root.go} (96%) delete mode 100644 cmd/utils.go diff --git a/cmd/action.go b/cmd/action.go index aed8025a0..3159115f9 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -27,7 +27,7 @@ func ActionCommand(cliConfig *Config) *cli.Command { $ shield action list `), Annotations: map[string]string{ - "action:core": "true", + "group:core": "true", }, } diff --git a/cmd/client.go b/cmd/client.go index c0ff227c6..b28866293 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -40,3 +40,23 @@ func createClient(cmd *cobra.Command) (shieldv1beta1.ShieldServiceClient, func() client := shieldv1beta1.NewShieldServiceClient(conn) return client, cancel, nil } + +func isClientCLI(cmd *cobra.Command) bool { + for c := cmd; c.Parent() != nil; c = c.Parent() { + if c.Annotations != nil && c.Annotations["client"] == "true" { + return true + } + } + return false +} + +func clientConfigHostExist(cmd *cobra.Command) bool { + host, err := cmd.Flags().GetString("host") + if err != nil { + return false + } + if host != "" { + return true + } + return false +} diff --git a/cmd/context.go b/cmd/context.go new file mode 100644 index 000000000..eec116d68 --- /dev/null +++ b/cmd/context.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "context" + "strings" + + "google.golang.org/grpc/metadata" +) + +func setCtxHeader(ctx context.Context, header string) context.Context { + s := strings.Split(header, ":") + key := s[0] + val := s[1] + + md := metadata.New(map[string]string{key: val}) + ctx = metadata.NewOutgoingContext(ctx, md) + + return ctx +} diff --git a/cmd/cmd.go b/cmd/root.go similarity index 96% rename from cmd/cmd.go rename to cmd/root.go index 65c360b54..dae6907e0 100644 --- a/cmd/cmd.go +++ b/cmd/root.go @@ -14,7 +14,7 @@ func New(cfg *Config) *cli.Command { Use: "shield [flags]", Short: "A cloud native role-based authorization aware reverse-proxy service", Long: heredoc.Doc(` - A cloud native role-based authorization aware reverse-proxy service.`), + A cloud native role-based authorization aware reverse-proxy service.`), SilenceUsage: true, SilenceErrors: true, Example: heredoc.Doc(` diff --git a/cmd/utils.go b/cmd/utils.go deleted file mode 100644 index 44328ed36..000000000 --- a/cmd/utils.go +++ /dev/null @@ -1,40 +0,0 @@ -package cmd - -import ( - "context" - "strings" - - "github.com/spf13/cobra" - "google.golang.org/grpc/metadata" -) - -func setCtxHeader(ctx context.Context, header string) context.Context { - s := strings.Split(header, ":") - key := s[0] - val := s[1] - - md := metadata.New(map[string]string{key: val}) - ctx = metadata.NewOutgoingContext(ctx, md) - - return ctx -} - -func isClientCLI(cmd *cobra.Command) bool { - for c := cmd; c.Parent() != nil; c = c.Parent() { - if c.Annotations != nil && c.Annotations["client"] == "true" { - return true - } - } - return false -} - -func clientConfigHostExist(cmd *cobra.Command) bool { - host, err := cmd.Flags().GetString("host") - if err != nil { - return false - } - if host != "" { - return true - } - return false -} From 0bb6b7dcb471e7d6f72a41b215032599b050d006 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Thu, 18 Aug 2022 11:25:08 +0700 Subject: [PATCH 07/16] feat(cmd): add test for error handling --- cmd/action.go | 1 + cmd/action_test.go | 119 ++++++++++++++++++++++++++++++++++++++ cmd/group_test.go | 119 ++++++++++++++++++++++++++++++++++++++ cmd/namespace_test.go | 119 ++++++++++++++++++++++++++++++++++++++ cmd/organization_test.go | 122 +++++++++++++++++++++++++++++++++++++++ cmd/policy_test.go | 119 ++++++++++++++++++++++++++++++++++++++ cmd/project_test.go | 119 ++++++++++++++++++++++++++++++++++++++ cmd/role_test.go | 119 ++++++++++++++++++++++++++++++++++++++ cmd/server.go | 2 +- config/config.go | 2 +- 10 files changed, 839 insertions(+), 2 deletions(-) create mode 100644 cmd/action_test.go create mode 100644 cmd/group_test.go create mode 100644 cmd/namespace_test.go create mode 100644 cmd/organization_test.go create mode 100644 cmd/policy_test.go create mode 100644 cmd/project_test.go create mode 100644 cmd/role_test.go diff --git a/cmd/action.go b/cmd/action.go index 3159115f9..a2ff9b070 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -28,6 +28,7 @@ func ActionCommand(cliConfig *Config) *cli.Command { `), Annotations: map[string]string{ "group:core": "true", + "client": "true", }, } diff --git a/cmd/action_test.go b/cmd/action_test.go new file mode 100644 index 000000000..787ee883b --- /dev/null +++ b/cmd/action_test.go @@ -0,0 +1,119 @@ +package cmd_test + +import ( + "bytes" + "context" + "errors" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/cmd" + "github.com/stretchr/testify/assert" +) + +var expectedActionUsageHelp = heredoc.Doc(` + +USAGE + shield action [flags] + +CORE COMMANDS + create Create an action + edit Edit an action + list List all actions + view View an action + +FLAGS + -h, --host string Shield API service to connect to + +INHERITED FLAGS + --help Show help for command + +EXAMPLES + $ shield action create + $ shield action edit + $ shield action view + $ shield action list + +`) + +func TestClientAction(t *testing.T) { + t.Run("without config file", func(t *testing.T) { + tests := []struct { + name string + cliConfig *cmd.Config + subCommands []string + want string + err error + }{ + { + name: "`action` only should show usage help", + want: expectedActionUsageHelp, + err: nil, + }, + { + name: "`action` list only should throw error host not found", + want: "", + subCommands: []string{"list"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`action` list with host flag should pass", + want: "", + subCommands: []string{"list", "-h", "test"}, + err: context.DeadlineExceeded, + }, + { + name: "`action` create only should throw error host not found", + want: "", + subCommands: []string{"create"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`action` create with host flag should throw error missing required flag", + want: "", + subCommands: []string{"create", "-h", "test"}, + err: errors.New("required flag(s) \"file\", \"header\" not set"), + }, + { + name: "`action` edit without host should throw error host not found", + want: "", + subCommands: []string{"edit", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`action` edit with host flag should throw error missing required flag", + want: "", + subCommands: []string{"edit", "123", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`action` view without host should throw error host not found", + want: "", + subCommands: []string{"view", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`action` view with host flag should pass", + want: "", + subCommands: []string{"view", "123", "-h", "test"}, + err: context.DeadlineExceeded, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cli := cmd.New(tt.cliConfig) + + buf := new(bytes.Buffer) + cli.SetOutput(buf) + args := append([]string{"action"}, tt.subCommands...) + cli.SetArgs(args) + + err := cli.Execute() + got := buf.String() + + assert.Equal(t, tt.err, err) + assert.Equal(t, tt.want, got) + }) + } + }) +} diff --git a/cmd/group_test.go b/cmd/group_test.go new file mode 100644 index 000000000..12ea963d0 --- /dev/null +++ b/cmd/group_test.go @@ -0,0 +1,119 @@ +package cmd_test + +import ( + "bytes" + "context" + "errors" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/cmd" + "github.com/stretchr/testify/assert" +) + +var expectedGroupUsageHelp = heredoc.Doc(` + +USAGE + shield group [flags] + +CORE COMMANDS + create Create a group + edit Edit a group + list List all groups + view View a group + +FLAGS + -h, --host string Shield API service to connect to + +INHERITED FLAGS + --help Show help for command + +EXAMPLES + $ shield group create + $ shield group edit + $ shield group view + $ shield group list + +`) + +func TestClientGroup(t *testing.T) { + t.Run("without config file", func(t *testing.T) { + tests := []struct { + name string + cliConfig *cmd.Config + subCommands []string + want string + err error + }{ + { + name: "`group` only should show usage help", + want: expectedGroupUsageHelp, + err: nil, + }, + { + name: "`group` list only should throw error host not found", + want: "", + subCommands: []string{"list"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`group` list with host flag should pass", + want: "", + subCommands: []string{"list", "-h", "test"}, + err: context.DeadlineExceeded, + }, + { + name: "`group` create only should throw error host not found", + want: "", + subCommands: []string{"create"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`group` create with host flag should throw error missing required flag", + want: "", + subCommands: []string{"create", "-h", "test"}, + err: errors.New("required flag(s) \"file\", \"header\" not set"), + }, + { + name: "`group` edit without host should throw error host not found", + want: "", + subCommands: []string{"edit", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`group` edit with host flag should throw error missing required flag", + want: "", + subCommands: []string{"edit", "123", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`group` view without host should throw error host not found", + want: "", + subCommands: []string{"view", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`group` view with host flag should pass", + want: "", + subCommands: []string{"view", "123", "-h", "test"}, + err: context.DeadlineExceeded, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cli := cmd.New(tt.cliConfig) + + buf := new(bytes.Buffer) + cli.SetOutput(buf) + args := append([]string{"group"}, tt.subCommands...) + cli.SetArgs(args) + + err := cli.Execute() + got := buf.String() + + assert.Equal(t, tt.err, err) + assert.Equal(t, tt.want, got) + }) + } + }) +} diff --git a/cmd/namespace_test.go b/cmd/namespace_test.go new file mode 100644 index 000000000..303fa8ee0 --- /dev/null +++ b/cmd/namespace_test.go @@ -0,0 +1,119 @@ +package cmd_test + +import ( + "bytes" + "context" + "errors" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/cmd" + "github.com/stretchr/testify/assert" +) + +var expectedNamespaceUsageHelp = heredoc.Doc(` + +USAGE + shield namespace [flags] + +CORE COMMANDS + create Create a namespace + edit Edit a namespace + list List all namespaces + view View a namespace + +FLAGS + -h, --host string Shield API service to connect to + +INHERITED FLAGS + --help Show help for command + +EXAMPLES + $ shield namespace create + $ shield namespace edit + $ shield namespace view + $ shield namespace list + +`) + +func TestClientNamespace(t *testing.T) { + t.Run("without config file", func(t *testing.T) { + tests := []struct { + name string + cliConfig *cmd.Config + subCommands []string + want string + err error + }{ + { + name: "`namespace` only should show usage help", + want: expectedNamespaceUsageHelp, + err: nil, + }, + { + name: "`namespace` list only should throw error host not found", + want: "", + subCommands: []string{"list"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`namespace` list with host flag should pass", + want: "", + subCommands: []string{"list", "-h", "test"}, + err: context.DeadlineExceeded, + }, + { + name: "`namespace` create only should throw error host not found", + want: "", + subCommands: []string{"create"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`namespace` create with host flag should throw error missing required flag", + want: "", + subCommands: []string{"create", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`namespace` edit without host should throw error host not found", + want: "", + subCommands: []string{"edit", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`namespace` edit with host flag should throw error missing required flag", + want: "", + subCommands: []string{"edit", "123", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`namespace` view without host should throw error host not found", + want: "", + subCommands: []string{"view", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`namespace` view with host flag should pass", + want: "", + subCommands: []string{"view", "123", "-h", "test"}, + err: context.DeadlineExceeded, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cli := cmd.New(tt.cliConfig) + + buf := new(bytes.Buffer) + cli.SetOutput(buf) + args := append([]string{"namespace"}, tt.subCommands...) + cli.SetArgs(args) + + err := cli.Execute() + got := buf.String() + + assert.Equal(t, tt.err, err) + assert.Equal(t, tt.want, got) + }) + } + }) +} diff --git a/cmd/organization_test.go b/cmd/organization_test.go new file mode 100644 index 000000000..b85e69db9 --- /dev/null +++ b/cmd/organization_test.go @@ -0,0 +1,122 @@ +package cmd_test + +import ( + "bytes" + "context" + "errors" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/cmd" + "github.com/stretchr/testify/assert" +) + +var expectedOrganizationUsageHelp = heredoc.Doc(` + +USAGE + shield organization [flags] + +CORE COMMANDS + admadd add admins to an organization + admlist list admins of an organization + admremove remove admins from an organization + create Create an organization + edit Edit an organization + list List all organizations + view View an organization + +FLAGS + -h, --host string Shield API service to connect to + +INHERITED FLAGS + --help Show help for command + +EXAMPLES + $ shield organization create + $ shield organization edit + $ shield organization view + $ shield organization list + +`) + +func TestClientOrganization(t *testing.T) { + t.Run("without config file", func(t *testing.T) { + tests := []struct { + name string + cliConfig *cmd.Config + subCommands []string + want string + err error + }{ + { + name: "`organization` only should show usage help", + want: expectedOrganizationUsageHelp, + err: nil, + }, + { + name: "`organization` list only should throw error host not found", + want: "", + subCommands: []string{"list"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`organization` list with host flag should pass", + want: "", + subCommands: []string{"list", "-h", "test"}, + err: context.DeadlineExceeded, + }, + { + name: "`organization` create only should throw error host not found", + want: "", + subCommands: []string{"create"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`organization` create with host flag should throw error missing required flag", + want: "", + subCommands: []string{"create", "-h", "test"}, + err: errors.New("required flag(s) \"file\", \"header\" not set"), + }, + { + name: "`organization` edit without host should throw error host not found", + want: "", + subCommands: []string{"edit", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`organization` edit with host flag should throw error missing required flag", + want: "", + subCommands: []string{"edit", "123", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`organization` view without host should throw error host not found", + want: "", + subCommands: []string{"view", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`organization` view with host flag should pass", + want: "", + subCommands: []string{"view", "123", "-h", "test"}, + err: context.DeadlineExceeded, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cli := cmd.New(tt.cliConfig) + + buf := new(bytes.Buffer) + cli.SetOutput(buf) + args := append([]string{"organization"}, tt.subCommands...) + cli.SetArgs(args) + + err := cli.Execute() + got := buf.String() + + assert.Equal(t, tt.err, err) + assert.Equal(t, tt.want, got) + }) + } + }) +} diff --git a/cmd/policy_test.go b/cmd/policy_test.go new file mode 100644 index 000000000..f1a3aeb40 --- /dev/null +++ b/cmd/policy_test.go @@ -0,0 +1,119 @@ +package cmd_test + +import ( + "bytes" + "context" + "errors" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/cmd" + "github.com/stretchr/testify/assert" +) + +var expectedPolicyUsageHelp = heredoc.Doc(` + +USAGE + shield policy [flags] + +CORE COMMANDS + create Create a policy + edit Edit a policy + list List all policies + view View a policy + +FLAGS + -h, --host string Shield API service to connect to + +INHERITED FLAGS + --help Show help for command + +EXAMPLES + $ shield policy create + $ shield policy edit + $ shield policy view + $ shield policy list + +`) + +func TestClientPolicy(t *testing.T) { + t.Run("without config file", func(t *testing.T) { + tests := []struct { + name string + cliConfig *cmd.Config + subCommands []string + want string + err error + }{ + { + name: "`policy` only should show usage help", + want: expectedPolicyUsageHelp, + err: nil, + }, + { + name: "`policy` list only should throw error host not found", + want: "", + subCommands: []string{"list"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`policy` list with host flag should pass", + want: "", + subCommands: []string{"list", "-h", "test"}, + err: context.DeadlineExceeded, + }, + { + name: "`policy` create only should throw error host not found", + want: "", + subCommands: []string{"create"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`policy` create with host flag should throw error missing required flag", + want: "", + subCommands: []string{"create", "-h", "test"}, + err: errors.New("required flag(s) \"file\", \"header\" not set"), + }, + { + name: "`policy` edit without host should throw error host not found", + want: "", + subCommands: []string{"edit", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`policy` edit with host flag should throw error missing required flag", + want: "", + subCommands: []string{"edit", "123", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`policy` view without host should throw error host not found", + want: "", + subCommands: []string{"view", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`policy` view with host flag should pass", + want: "", + subCommands: []string{"view", "123", "-h", "test"}, + err: context.DeadlineExceeded, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cli := cmd.New(tt.cliConfig) + + buf := new(bytes.Buffer) + cli.SetOutput(buf) + args := append([]string{"policy"}, tt.subCommands...) + cli.SetArgs(args) + + err := cli.Execute() + got := buf.String() + + assert.Equal(t, tt.err, err) + assert.Equal(t, tt.want, got) + }) + } + }) +} diff --git a/cmd/project_test.go b/cmd/project_test.go new file mode 100644 index 000000000..8d61d5024 --- /dev/null +++ b/cmd/project_test.go @@ -0,0 +1,119 @@ +package cmd_test + +import ( + "bytes" + "context" + "errors" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/cmd" + "github.com/stretchr/testify/assert" +) + +var expectedProjectUsageHelp = heredoc.Doc(` + +USAGE + shield project [flags] + +CORE COMMANDS + create Create a project + edit Edit a project + list List all projects + view View a project + +FLAGS + -h, --host string Shield API service to connect to + +INHERITED FLAGS + --help Show help for command + +EXAMPLES + $ shield project create + $ shield project edit + $ shield project view + $ shield project list + +`) + +func TestClientProject(t *testing.T) { + t.Run("without config file", func(t *testing.T) { + tests := []struct { + name string + cliConfig *cmd.Config + subCommands []string + want string + err error + }{ + { + name: "`project` only should show usage help", + want: expectedProjectUsageHelp, + err: nil, + }, + { + name: "`project` list only should throw error host not found", + want: "", + subCommands: []string{"list"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`project` list with host flag should pass", + want: "", + subCommands: []string{"list", "-h", "test"}, + err: context.DeadlineExceeded, + }, + { + name: "`project` create only should throw error host not found", + want: "", + subCommands: []string{"create"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`project` create with host flag should throw error missing required flag", + want: "", + subCommands: []string{"create", "-h", "test"}, + err: errors.New("required flag(s) \"file\", \"header\" not set"), + }, + { + name: "`project` edit without host should throw error host not found", + want: "", + subCommands: []string{"edit", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`project` edit with host flag should throw error missing required flag", + want: "", + subCommands: []string{"edit", "123", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`project` view without host should throw error host not found", + want: "", + subCommands: []string{"view", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`project` view with host flag should pass", + want: "", + subCommands: []string{"view", "123", "-h", "test"}, + err: context.DeadlineExceeded, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cli := cmd.New(tt.cliConfig) + + buf := new(bytes.Buffer) + cli.SetOutput(buf) + args := append([]string{"project"}, tt.subCommands...) + cli.SetArgs(args) + + err := cli.Execute() + got := buf.String() + + assert.Equal(t, tt.err, err) + assert.Equal(t, tt.want, got) + }) + } + }) +} diff --git a/cmd/role_test.go b/cmd/role_test.go new file mode 100644 index 000000000..7f33d1ed2 --- /dev/null +++ b/cmd/role_test.go @@ -0,0 +1,119 @@ +package cmd_test + +import ( + "bytes" + "context" + "errors" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/odpf/shield/cmd" + "github.com/stretchr/testify/assert" +) + +var expectedRoleUsageHelp = heredoc.Doc(` + +USAGE + shield role [flags] + +CORE COMMANDS + create Create a role + edit Edit a role + list List all roles + view View a role + +FLAGS + -h, --host string Shield API service to connect to + +INHERITED FLAGS + --help Show help for command + +EXAMPLES + $ shield role create + $ shield role edit + $ shield role view + $ shield role list + +`) + +func TestClientRole(t *testing.T) { + t.Run("without config file", func(t *testing.T) { + tests := []struct { + name string + cliConfig *cmd.Config + subCommands []string + want string + err error + }{ + { + name: "`role` only should show usage help", + want: expectedRoleUsageHelp, + err: nil, + }, + { + name: "`role` list only should throw error host not found", + want: "", + subCommands: []string{"list"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`role` list with host flag should pass", + want: "", + subCommands: []string{"list", "-h", "test"}, + err: context.DeadlineExceeded, + }, + { + name: "`role` create only should throw error host not found", + want: "", + subCommands: []string{"create"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`role` create with host flag should throw error missing required flag", + want: "", + subCommands: []string{"create", "-h", "test"}, + err: errors.New("required flag(s) \"file\", \"header\" not set"), + }, + { + name: "`role` edit without host should throw error host not found", + want: "", + subCommands: []string{"edit", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`role` edit with host flag should throw error missing required flag", + want: "", + subCommands: []string{"edit", "123", "-h", "test"}, + err: errors.New("required flag(s) \"file\" not set"), + }, + { + name: "`role` view without host should throw error host not found", + want: "", + subCommands: []string{"view", "123"}, + err: cmd.ErrClientConfigHostNotFound, + }, + { + name: "`role` view with host flag should pass", + want: "", + subCommands: []string{"view", "123", "-h", "test"}, + err: context.DeadlineExceeded, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cli := cmd.New(tt.cliConfig) + + buf := new(bytes.Buffer) + cli.SetOutput(buf) + args := append([]string{"role"}, tt.subCommands...) + cli.SetArgs(args) + + err := cli.Execute() + got := buf.String() + + assert.Equal(t, tt.err, err) + assert.Equal(t, tt.want, got) + }) + } + }) +} diff --git a/cmd/server.go b/cmd/server.go index 8a0225ab5..8b20f0ce0 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -71,7 +71,7 @@ func serverInitCommand() *cobra.Command { return err } - fmt.Printf("config created: %v\n", configFile) + fmt.Printf("server config created: %v\n", configFile) return nil }, } diff --git a/config/config.go b/config/config.go index 38470e7e2..77d15f876 100644 --- a/config/config.go +++ b/config/config.go @@ -21,7 +21,7 @@ type Shield struct { NewRelic NewRelic `yaml:"new_relic"` App server.Config `yaml:"app"` DB db.Config `yaml:"db"` - SpiceDB spicedb.Config `yaml:"spice_db"` + SpiceDB spicedb.Config `yaml:"spicedb"` } type NewRelic struct { From 415cff3434f6bbcf1f80282dbc93a8e33b386f65 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Thu, 18 Aug 2022 11:50:34 +0700 Subject: [PATCH 08/16] fix(cmd): default server config --- cmd/help.go | 2 +- cmd/server.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/help.go b/cmd/help.go index 79081eab7..752b804aa 100644 --- a/cmd/help.go +++ b/cmd/help.go @@ -17,6 +17,6 @@ var authHelp = map[string]string{ "long": heredoc.Doc(` Send an additional flag header with "key:value" format. Example: - shield create user -f user.yaml -h X-Shield-Email:user@odpf.io + shield create user -f user.yaml -H X-Shield-Email:user@odpf.io `), } diff --git a/cmd/server.go b/cmd/server.go index 8b20f0ce0..9f197ec1f 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -113,7 +113,7 @@ func serverStartCommand() *cobra.Command { }, } - c.Flags().StringVarP(&configFile, "config", "c", "./config.yaml", "Config file path") + c.Flags().StringVarP(&configFile, "config", "c", "", "Config file path") return c } @@ -137,7 +137,7 @@ func serverMigrateCommand() *cobra.Command { }, } - c.Flags().StringVarP(&configFile, "config", "c", "./config.yaml", "Config file path") + c.Flags().StringVarP(&configFile, "config", "c", "", "Config file path") return c } From 4734057adde33e219b833468302930d831717473 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Thu, 18 Aug 2022 13:02:10 +0700 Subject: [PATCH 09/16] fix(cmd): make cmd.Config as a source of truth --- cmd/action.go | 22 ++++++++-------------- cmd/action_test.go | 1 + cmd/client.go | 33 +++++++++++++++++++-------------- cmd/config.go | 10 ---------- cmd/group.go | 21 ++++++++------------- cmd/group_test.go | 1 + cmd/namespace.go | 21 ++++++++------------- cmd/namespace_test.go | 1 + cmd/organization.go | 37 ++++++++++++++----------------------- cmd/organization_test.go | 1 + cmd/policy.go | 22 ++++++++-------------- cmd/policy_test.go | 1 + cmd/project.go | 22 ++++++++-------------- cmd/project_test.go | 1 + cmd/role.go | 21 ++++++++------------- cmd/role_test.go | 1 + cmd/root.go | 4 ++-- cmd/user.go | 8 ++++---- 18 files changed, 94 insertions(+), 134 deletions(-) diff --git a/cmd/action.go b/cmd/action.go index a2ff9b070..f5e90e881 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" @@ -69,15 +68,13 @@ func createActionCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - ctx = setCtxHeader(ctx, header) - + ctx := setCtxHeader(cmd.Context(), header) res, err := client.CreateAction(ctx, &shieldv1beta1.CreateActionRequest{ Body: &reqBody, }) @@ -126,15 +123,14 @@ func editActionCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() actionID := args[0] - _, err = client.UpdateAction(ctx, &shieldv1beta1.UpdateActionRequest{ + _, err = client.UpdateAction(cmd.Context(), &shieldv1beta1.UpdateActionRequest{ Id: actionID, Body: &reqBody, }) @@ -169,15 +165,14 @@ func viewActionCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() actionID := args[0] - res, err := client.GetAction(ctx, &shieldv1beta1.GetActionRequest{ + res, err := client.GetAction(cmd.Context(), &shieldv1beta1.GetActionRequest{ Id: actionID, }) if err != nil { @@ -220,14 +215,13 @@ func listActionCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.ListActions(ctx, &shieldv1beta1.ListActionsRequest{}) + res, err := client.ListActions(cmd.Context(), &shieldv1beta1.ListActionsRequest{}) if err != nil { return err } diff --git a/cmd/action_test.go b/cmd/action_test.go index 787ee883b..3f61bb1ee 100644 --- a/cmd/action_test.go +++ b/cmd/action_test.go @@ -101,6 +101,7 @@ func TestClientAction(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.cliConfig = &cmd.Config{} cli := cmd.New(tt.cliConfig) buf := new(bytes.Buffer) diff --git a/cmd/client.go b/cmd/client.go index b28866293..6d89be176 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -19,19 +19,13 @@ func createConnection(ctx context.Context, host string) (*grpc.ClientConn, error return grpc.DialContext(ctx, host, opts...) } -func createClient(cmd *cobra.Command) (shieldv1beta1.ShieldServiceClient, func(), error) { - dialTimeoutCtx, dialCancel := context.WithTimeout(cmd.Context(), time.Second*2) - host, err := cmd.Flags().GetString("host") - if err != nil { - dialCancel() - return nil, nil, err - } +func createClient(ctx context.Context, host string) (shieldv1beta1.ShieldServiceClient, func(), error) { + dialTimeoutCtx, dialCancel := context.WithTimeout(ctx, time.Second*2) conn, err := createConnection(dialTimeoutCtx, host) if err != nil { dialCancel() return nil, nil, err } - cancel := func() { dialCancel() conn.Close() @@ -50,13 +44,24 @@ func isClientCLI(cmd *cobra.Command) bool { return false } -func clientConfigHostExist(cmd *cobra.Command) bool { +func overrideClientConfigHost(cmd *cobra.Command, cliConfig *Config) error { + if cliConfig == nil { + return ErrClientConfigNotFound + } + host, err := cmd.Flags().GetString("host") - if err != nil { - return false + if err == nil && host != "" { + cliConfig.Host = host + return nil } - if host != "" { - return true + + if cliConfig.Host == "" { + return ErrClientConfigHostNotFound } - return false + + return nil +} + +func bindFlagsFromClientConfig(cmd *cobra.Command) { + cmd.PersistentFlags().StringP("host", "h", "", "Shield API service to connect to") } diff --git a/cmd/config.go b/cmd/config.go index 5dc4de947..3379352b7 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -85,13 +85,3 @@ func configListCommand() *cobra.Command { } return cmd } - -func bindFlagsFromClientConfig(cmd *cobra.Command) { - cmd.PersistentFlags().StringP("host", "h", "", "Shield API service to connect to") - - if cliConfig != nil { - if cliConfig.Host != "" { - cmd.PersistentFlags().Set("host", cliConfig.Host) - } - } -} diff --git a/cmd/group.go b/cmd/group.go index 0939eb163..6a33c8d8c 100644 --- a/cmd/group.go +++ b/cmd/group.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" @@ -69,14 +68,13 @@ func createGroupCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.CreateGroup(setCtxHeader(ctx, header), &shieldv1beta1.CreateGroupRequest{ + res, err := client.CreateGroup(setCtxHeader(cmd.Context(), header), &shieldv1beta1.CreateGroupRequest{ Body: &reqBody, }) if err != nil { @@ -124,15 +122,14 @@ func editGroupCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() groupID := args[0] - _, err = client.UpdateGroup(ctx, &shieldv1beta1.UpdateGroupRequest{ + _, err = client.UpdateGroup(cmd.Context(), &shieldv1beta1.UpdateGroupRequest{ Id: groupID, Body: &reqBody, }) @@ -169,15 +166,14 @@ func viewGroupCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() groupID := args[0] - res, err := client.GetGroup(ctx, &shieldv1beta1.GetGroupRequest{ + res, err := client.GetGroup(cmd.Context(), &shieldv1beta1.GetGroupRequest{ Id: groupID, }) if err != nil { @@ -240,14 +236,13 @@ func listGroupCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.ListGroups(ctx, &shieldv1beta1.ListGroupsRequest{}) + res, err := client.ListGroups(cmd.Context(), &shieldv1beta1.ListGroupsRequest{}) if err != nil { return err } diff --git a/cmd/group_test.go b/cmd/group_test.go index 12ea963d0..536fe6dc9 100644 --- a/cmd/group_test.go +++ b/cmd/group_test.go @@ -101,6 +101,7 @@ func TestClientGroup(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.cliConfig = &cmd.Config{} cli := cmd.New(tt.cliConfig) buf := new(bytes.Buffer) diff --git a/cmd/namespace.go b/cmd/namespace.go index c33684528..a00ab0488 100644 --- a/cmd/namespace.go +++ b/cmd/namespace.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" @@ -69,14 +68,13 @@ func createNamespaceCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.CreateNamespace(ctx, &shieldv1beta1.CreateNamespaceRequest{ + res, err := client.CreateNamespace(cmd.Context(), &shieldv1beta1.CreateNamespaceRequest{ Body: &reqBody, }) if err != nil { @@ -122,15 +120,14 @@ func editNamespaceCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() namespaceID := args[0] - res, err := client.UpdateNamespace(ctx, &shieldv1beta1.UpdateNamespaceRequest{ + res, err := client.UpdateNamespace(cmd.Context(), &shieldv1beta1.UpdateNamespaceRequest{ Id: namespaceID, Body: &reqBody, }) @@ -165,15 +162,14 @@ func viewNamespaceCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() namespaceID := args[0] - res, err := client.GetNamespace(ctx, &shieldv1beta1.GetNamespaceRequest{ + res, err := client.GetNamespace(cmd.Context(), &shieldv1beta1.GetNamespaceRequest{ Id: namespaceID, }) if err != nil { @@ -219,14 +215,13 @@ func listNamespaceCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.ListNamespaces(ctx, &shieldv1beta1.ListNamespacesRequest{}) + res, err := client.ListNamespaces(cmd.Context(), &shieldv1beta1.ListNamespacesRequest{}) if err != nil { return err } diff --git a/cmd/namespace_test.go b/cmd/namespace_test.go index 303fa8ee0..b5fa70c81 100644 --- a/cmd/namespace_test.go +++ b/cmd/namespace_test.go @@ -101,6 +101,7 @@ func TestClientNamespace(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.cliConfig = &cmd.Config{} cli := cmd.New(tt.cliConfig) buf := new(bytes.Buffer) diff --git a/cmd/organization.go b/cmd/organization.go index 4c347a4c6..17173ee75 100644 --- a/cmd/organization.go +++ b/cmd/organization.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" @@ -72,15 +71,13 @@ func createOrganizationCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - ctx = setCtxHeader(ctx, header) - + ctx := setCtxHeader(cmd.Context(), header) res, err := client.CreateOrganization(ctx, &shieldv1beta1.CreateOrganizationRequest{ Body: &reqBody, }) @@ -129,15 +126,14 @@ func editOrganizationCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() organizationID := args[0] - _, err = client.UpdateOrganization(ctx, &shieldv1beta1.UpdateOrganizationRequest{ + _, err = client.UpdateOrganization(cmd.Context(), &shieldv1beta1.UpdateOrganizationRequest{ Id: organizationID, Body: &reqBody, }) @@ -174,15 +170,14 @@ func viewOrganizationCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() organizationID := args[0] - res, err := client.GetOrganization(ctx, &shieldv1beta1.GetOrganizationRequest{ + res, err := client.GetOrganization(cmd.Context(), &shieldv1beta1.GetOrganizationRequest{ Id: organizationID, }) if err != nil { @@ -244,14 +239,13 @@ func listOrganizationCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.ListOrganizations(ctx, &shieldv1beta1.ListOrganizationsRequest{}) + res, err := client.ListOrganizations(cmd.Context(), &shieldv1beta1.ListOrganizationsRequest{}) if err != nil { return err } @@ -312,15 +306,14 @@ func admaddOrganizationCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() organizationID := args[0] - _, err = client.AddOrganizationAdmin(ctx, &shieldv1beta1.AddOrganizationAdminRequest{ + _, err = client.AddOrganizationAdmin(cmd.Context(), &shieldv1beta1.AddOrganizationAdminRequest{ Id: organizationID, Body: &reqBody, }) @@ -357,15 +350,14 @@ func admremoveOrganizationCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() organizationID := args[0] - _, err = client.RemoveOrganizationAdmin(ctx, &shieldv1beta1.RemoveOrganizationAdminRequest{ + _, err = client.RemoveOrganizationAdmin(cmd.Context(), &shieldv1beta1.RemoveOrganizationAdminRequest{ Id: organizationID, UserId: userID, }) @@ -400,15 +392,14 @@ func admlistOrganizationCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() organizationID := args[0] - res, err := client.ListOrganizationAdmins(ctx, &shieldv1beta1.ListOrganizationAdminsRequest{ + res, err := client.ListOrganizationAdmins(cmd.Context(), &shieldv1beta1.ListOrganizationAdminsRequest{ Id: organizationID, }) if err != nil { diff --git a/cmd/organization_test.go b/cmd/organization_test.go index b85e69db9..d1d1a9fe8 100644 --- a/cmd/organization_test.go +++ b/cmd/organization_test.go @@ -104,6 +104,7 @@ func TestClientOrganization(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.cliConfig = &cmd.Config{} cli := cmd.New(tt.cliConfig) buf := new(bytes.Buffer) diff --git a/cmd/policy.go b/cmd/policy.go index 92b47eaf3..ef9b99ff2 100644 --- a/cmd/policy.go +++ b/cmd/policy.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" @@ -69,15 +68,13 @@ func createPolicyCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - ctx = setCtxHeader(ctx, header) - + ctx := setCtxHeader(cmd.Context(), header) _, err = client.CreatePolicy(ctx, &shieldv1beta1.CreatePolicyRequest{ Body: &reqBody, }) @@ -126,15 +123,14 @@ func editPolicyCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() policyID := args[0] - _, err = client.UpdatePolicy(ctx, &shieldv1beta1.UpdatePolicyRequest{ + _, err = client.UpdatePolicy(cmd.Context(), &shieldv1beta1.UpdatePolicyRequest{ Id: policyID, Body: &reqBody, }) @@ -169,15 +165,14 @@ func viewPolicyCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() policyID := args[0] - res, err := client.GetPolicy(ctx, &shieldv1beta1.GetPolicyRequest{ + res, err := client.GetPolicy(cmd.Context(), &shieldv1beta1.GetPolicyRequest{ Id: policyID, }) if err != nil { @@ -220,14 +215,13 @@ func listPolicyCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.ListPolicies(ctx, &shieldv1beta1.ListPoliciesRequest{}) + res, err := client.ListPolicies(cmd.Context(), &shieldv1beta1.ListPoliciesRequest{}) if err != nil { return err } diff --git a/cmd/policy_test.go b/cmd/policy_test.go index f1a3aeb40..d0a636380 100644 --- a/cmd/policy_test.go +++ b/cmd/policy_test.go @@ -101,6 +101,7 @@ func TestClientPolicy(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.cliConfig = &cmd.Config{} cli := cmd.New(tt.cliConfig) buf := new(bytes.Buffer) diff --git a/cmd/project.go b/cmd/project.go index 8e67c5f50..fac5dcce8 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" @@ -69,15 +68,13 @@ func createProjectCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - ctx = setCtxHeader(ctx, header) - + ctx := setCtxHeader(cmd.Context(), header) res, err := client.CreateProject(ctx, &shieldv1beta1.CreateProjectRequest{ Body: &reqBody, }) @@ -126,15 +123,14 @@ func editProjectCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() projectID := args[0] - _, err = client.UpdateProject(ctx, &shieldv1beta1.UpdateProjectRequest{ + _, err = client.UpdateProject(cmd.Context(), &shieldv1beta1.UpdateProjectRequest{ Id: projectID, Body: &reqBody, }) @@ -171,15 +167,14 @@ func viewProjectCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() projectID := args[0] - res, err := client.GetProject(ctx, &shieldv1beta1.GetProjectRequest{ + res, err := client.GetProject(cmd.Context(), &shieldv1beta1.GetProjectRequest{ Id: projectID, }) if err != nil { @@ -242,14 +237,13 @@ func listProjectCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.ListProjects(ctx, &shieldv1beta1.ListProjectsRequest{}) + res, err := client.ListProjects(cmd.Context(), &shieldv1beta1.ListProjectsRequest{}) if err != nil { return err } diff --git a/cmd/project_test.go b/cmd/project_test.go index 8d61d5024..cf6fb7450 100644 --- a/cmd/project_test.go +++ b/cmd/project_test.go @@ -101,6 +101,7 @@ func TestClientProject(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.cliConfig = &cmd.Config{} cli := cmd.New(tt.cliConfig) buf := new(bytes.Buffer) diff --git a/cmd/role.go b/cmd/role.go index c3303bd5b..767cab749 100644 --- a/cmd/role.go +++ b/cmd/role.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" "strings" @@ -70,14 +69,13 @@ func createRoleCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - ctx = setCtxHeader(ctx, header) + ctx := setCtxHeader(cmd.Context(), header) res, err := client.CreateRole(ctx, &shieldv1beta1.CreateRoleRequest{ Body: &reqBody, @@ -127,15 +125,14 @@ func editRoleCommand(cliConfig *Config) *cli.Command { return err } - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() roleID := args[0] - _, err = client.UpdateRole(ctx, &shieldv1beta1.UpdateRoleRequest{ + _, err = client.UpdateRole(cmd.Context(), &shieldv1beta1.UpdateRoleRequest{ Id: roleID, Body: &reqBody, }) @@ -172,15 +169,14 @@ func viewRoleCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() roleID := args[0] - res, err := client.GetRole(ctx, &shieldv1beta1.GetRoleRequest{ + res, err := client.GetRole(cmd.Context(), &shieldv1beta1.GetRoleRequest{ Id: roleID, }) if err != nil { @@ -243,14 +239,13 @@ func listRoleCommand(cliConfig *Config) *cli.Command { spinner := printer.Spin("") defer spinner.Stop() - ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } defer cancel() - res, err := client.ListRoles(ctx, &shieldv1beta1.ListRolesRequest{}) + res, err := client.ListRoles(cmd.Context(), &shieldv1beta1.ListRolesRequest{}) if err != nil { return err } diff --git a/cmd/role_test.go b/cmd/role_test.go index 7f33d1ed2..b34716b2f 100644 --- a/cmd/role_test.go +++ b/cmd/role_test.go @@ -101,6 +101,7 @@ func TestClientRole(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + tt.cliConfig = &cmd.Config{} cli := cmd.New(tt.cliConfig) buf := new(bytes.Buffer) diff --git a/cmd/root.go b/cmd/root.go index dae6907e0..6dbede7af 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -40,8 +40,8 @@ func New(cfg *Config) *cli.Command { cmd.PersistentPreRunE = func(subCmd *cobra.Command, args []string) error { if isClientCLI(subCmd) { - if !clientConfigHostExist(subCmd) { - return ErrClientConfigHostNotFound + if err := overrideClientConfigHost(subCmd, cliConfig); err != nil { + return err } } return nil diff --git a/cmd/user.go b/cmd/user.go index e7b800fd7..263d98647 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -70,7 +70,7 @@ func createUserCommand(cliConfig *Config) *cli.Command { } ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } @@ -125,7 +125,7 @@ func editUserCommand(cliConfig *Config) *cli.Command { } ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } @@ -170,7 +170,7 @@ func viewUserCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } @@ -235,7 +235,7 @@ func listUserCommand(cliConfig *Config) *cli.Command { defer spinner.Stop() ctx := context.Background() - client, cancel, err := createClient(cmd) + client, cancel, err := createClient(cmd.Context(), cliConfig.Host) if err != nil { return err } From e343fa7cc22cc7cfa3ef95b447482424b771b146 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Thu, 18 Aug 2022 14:32:24 +0700 Subject: [PATCH 10/16] refactor(config): rename serverConfigfileFromFlag --- config/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index 77d15f876..790cdf488 100644 --- a/config/config.go +++ b/config/config.go @@ -30,7 +30,7 @@ type NewRelic struct { Enabled bool `yaml:"enabled" mapstructure:"enabled"` } -func Load(configfileFromFlag string) (*Shield, error) { +func Load(serverConfigfileFromFlag string) (*Shield, error) { conf := &Shield{} var options []config.LoaderOption @@ -49,8 +49,8 @@ func Load(configfileFromFlag string) (*Shield, error) { } // override all config sources and prioritize one from file - if configfileFromFlag != "" { - options = []config.LoaderOption{config.WithFile(configfileFromFlag)} + if serverConfigfileFromFlag != "" { + options = []config.LoaderOption{config.WithFile(serverConfigfileFromFlag)} } l := config.NewLoader(options...) From a30bfaac979ae982591f049986be1904fea26ce4 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Fri, 19 Aug 2022 09:50:09 +0700 Subject: [PATCH 11/16] fix: move sample server config and update --- .shield.sample.yaml | 30 ---------------------- config/.shield.sample.yaml | 52 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 30 deletions(-) delete mode 100644 .shield.sample.yaml create mode 100644 config/.shield.sample.yaml diff --git a/.shield.sample.yaml b/.shield.sample.yaml deleted file mode 100644 index fbf5a428d..000000000 --- a/.shield.sample.yaml +++ /dev/null @@ -1,30 +0,0 @@ -version: 1 - -# logging configuration -log: - # debug, info, warning, error, fatal - default 'info' - level: debug - -# proxy configuration -proxy: - services: - - name: test - host: 0.0.0.0 - # port where the proxy will be listening on for requests - port: 5556 - - # full path prefixed with scheme where ruleset yaml files are kept - # e.g.: - # local storage file "file:///tmp/rules" - # GCS Bucket "gs://shield-bucket-example" - ruleset: file://absolute_path_to_rules_directory - - # secret required to access ruleset - # e.g.: - # system environment variable "env://TEST_RULESET_SECRET" - # local file "file:///opt/auth.json" - # secret string "val://user:password" - # - # +optional - # ruleset_secret: env://TEST_RULESET_SECRET - resources_config_path: file://absolute_path_to_rules_directory \ No newline at end of file diff --git a/config/.shield.sample.yaml b/config/.shield.sample.yaml new file mode 100644 index 000000000..618f12abc --- /dev/null +++ b/config/.shield.sample.yaml @@ -0,0 +1,52 @@ +version: 1 + +# logging configuration +log: + # debug, info, warning, error, fatal - default 'info' + level: debug + +app: + port: 8000 + identity_proxy_header: X-Shield-Email + # full path prefixed with scheme where resources config yaml files are kept + # e.g.: + # local storage file "file:///tmp/resources_config" + # GCS Bucket "gs://shield/resources_config" + resources_config_path: file:///tmp/resources_config\ + # secret required to access resources config + # e.g.: + # system environment variable "env://TEST_RULESET_SECRET" + # local file "file:///opt/auth.json" + # secret string "val://user:password" + # optional + resources_config_path_secret: env://TEST_RESOURCE_CONFIG_SECRET + +db: + driver: postgres + url: postgres://shield:@localhost:5432/shield?sslmode=disable + max_query_timeout: 500ms + +spicedb: + host: spicedb.localhost + pre_shared_key: randomkey + port: 50051 + +# proxy configuration +proxy: + services: + - name: test + host: 0.0.0.0 + # port where the proxy will be listening on for requests + port: 5556 + # full path prefixed with scheme where ruleset yaml files are kept + # e.g.: + # local storage file "file:///tmp/rules" + # GCS Bucket "gs://shield/rules" + ruleset: file:///tmp/rules + # secret required to access ruleset + # e.g.: + # system environment variable "env://TEST_RULESET_SECRET" + # local file "file:///opt/auth.json" + # secret string "val://user:password" + # optional + ruleset_secret: env://TEST_RULESET_SECRET \ No newline at end of file From 84ccf2ce9d2d8adb0a94d200aa53420441177228 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Fri, 19 Aug 2022 10:49:55 +0700 Subject: [PATCH 12/16] refactor: rename .shield.yaml to config.yaml --- .gitignore | 2 +- cmd/server.go | 6 +-- config/.shield.sample.yaml | 52 --------------------- config/config.go | 2 +- docs/docs/getting-started/configurations.md | 2 +- 5 files changed, 6 insertions(+), 58 deletions(-) delete mode 100644 config/.shield.sample.yaml diff --git a/.gitignore b/.gitignore index 4195a26bf..db33577a5 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ proxies/*.yml temp shield !proto/* -.shield.yaml +config.yaml dist coverage.txt coverage.out diff --git a/cmd/server.go b/cmd/server.go index 9f197ec1f..6d9731e50 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -49,7 +49,7 @@ func serverInitCommand() *cobra.Command { Short: "Initialize server", Long: heredoc.Doc(` Initializing server. Creating a sample of shield server config. - Default: ./.shield.yaml + Default: ./config.yaml `), Example: "shield server init", RunE: func(cmd *cli.Command, args []string) error { @@ -76,7 +76,7 @@ func serverInitCommand() *cobra.Command { }, } - c.Flags().StringVarP(&configFile, "output", "o", "./.shield.yaml", "Output config file path") + c.Flags().StringVarP(&configFile, "output", "o", "./config.yaml", "Output config file path") c.Flags().StringVarP(&resourcesURL, "resources", "r", "", heredoc.Doc(` URL path of resources. Full path prefixed with scheme where resources config yaml files are kept e.g.: @@ -161,6 +161,6 @@ func serverMigrateRollbackCommand() *cobra.Command { }, } - c.Flags().StringVarP(&configFile, "config", "c", "./config.yaml", "Config file path") + c.Flags().StringVarP(&configFile, "config", "c", "", "Config file path") return c } diff --git a/config/.shield.sample.yaml b/config/.shield.sample.yaml deleted file mode 100644 index 618f12abc..000000000 --- a/config/.shield.sample.yaml +++ /dev/null @@ -1,52 +0,0 @@ -version: 1 - -# logging configuration -log: - # debug, info, warning, error, fatal - default 'info' - level: debug - -app: - port: 8000 - identity_proxy_header: X-Shield-Email - # full path prefixed with scheme where resources config yaml files are kept - # e.g.: - # local storage file "file:///tmp/resources_config" - # GCS Bucket "gs://shield/resources_config" - resources_config_path: file:///tmp/resources_config\ - # secret required to access resources config - # e.g.: - # system environment variable "env://TEST_RULESET_SECRET" - # local file "file:///opt/auth.json" - # secret string "val://user:password" - # optional - resources_config_path_secret: env://TEST_RESOURCE_CONFIG_SECRET - -db: - driver: postgres - url: postgres://shield:@localhost:5432/shield?sslmode=disable - max_query_timeout: 500ms - -spicedb: - host: spicedb.localhost - pre_shared_key: randomkey - port: 50051 - -# proxy configuration -proxy: - services: - - name: test - host: 0.0.0.0 - # port where the proxy will be listening on for requests - port: 5556 - # full path prefixed with scheme where ruleset yaml files are kept - # e.g.: - # local storage file "file:///tmp/rules" - # GCS Bucket "gs://shield/rules" - ruleset: file:///tmp/rules - # secret required to access ruleset - # e.g.: - # system environment variable "env://TEST_RULESET_SECRET" - # local file "file:///opt/auth.json" - # secret string "val://user:password" - # optional - ruleset_secret: env://TEST_RULESET_SECRET \ No newline at end of file diff --git a/config/config.go b/config/config.go index 790cdf488..e1da6f1d4 100644 --- a/config/config.go +++ b/config/config.go @@ -34,7 +34,7 @@ func Load(serverConfigfileFromFlag string) (*Shield, error) { conf := &Shield{} var options []config.LoaderOption - options = append(options, config.WithName(".shield.yaml")) + options = append(options, config.WithName("config.yaml")) options = append(options, config.WithEnvKeyReplacer(".", "_")) options = append(options, config.WithEnvPrefix("SHIELD")) if p, err := os.Getwd(); err == nil { diff --git a/docs/docs/getting-started/configurations.md b/docs/docs/getting-started/configurations.md index 7f944bdb3..9f5f66782 100644 --- a/docs/docs/getting-started/configurations.md +++ b/docs/docs/getting-started/configurations.md @@ -1,6 +1,6 @@ ## Configurations -Shield can be configured with .shield.yaml file. An example of such is: +Shield can be configured with config.yaml file. An example of such is: ```yaml version: 1 From 0ef99b4dface81ade3019f2d3b032ea92e268001 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Fri, 19 Aug 2022 11:31:57 +0700 Subject: [PATCH 13/16] fix: .gitignore --- .gitignore | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index db33577a5..719f863c6 100644 --- a/.gitignore +++ b/.gitignore @@ -9,15 +9,14 @@ proxies/*.yml temp shield !proto/* -config.yaml +/config.yaml dist coverage.txt coverage.out -rules/test.yaml *.pprof ignore/ vendor/ buf.lock buf.yaml -resources_config -rules \ No newline at end of file +/resources_config +/rules \ No newline at end of file From 40c9b97627f36e83502d47b6ebddf19aae21db7d Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Fri, 19 Aug 2022 11:34:10 +0700 Subject: [PATCH 14/16] fix: add missing config.yaml --- config/config.yaml | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 config/config.yaml diff --git a/config/config.yaml b/config/config.yaml new file mode 100644 index 000000000..618f12abc --- /dev/null +++ b/config/config.yaml @@ -0,0 +1,52 @@ +version: 1 + +# logging configuration +log: + # debug, info, warning, error, fatal - default 'info' + level: debug + +app: + port: 8000 + identity_proxy_header: X-Shield-Email + # full path prefixed with scheme where resources config yaml files are kept + # e.g.: + # local storage file "file:///tmp/resources_config" + # GCS Bucket "gs://shield/resources_config" + resources_config_path: file:///tmp/resources_config\ + # secret required to access resources config + # e.g.: + # system environment variable "env://TEST_RULESET_SECRET" + # local file "file:///opt/auth.json" + # secret string "val://user:password" + # optional + resources_config_path_secret: env://TEST_RESOURCE_CONFIG_SECRET + +db: + driver: postgres + url: postgres://shield:@localhost:5432/shield?sslmode=disable + max_query_timeout: 500ms + +spicedb: + host: spicedb.localhost + pre_shared_key: randomkey + port: 50051 + +# proxy configuration +proxy: + services: + - name: test + host: 0.0.0.0 + # port where the proxy will be listening on for requests + port: 5556 + # full path prefixed with scheme where ruleset yaml files are kept + # e.g.: + # local storage file "file:///tmp/rules" + # GCS Bucket "gs://shield/rules" + ruleset: file:///tmp/rules + # secret required to access ruleset + # e.g.: + # system environment variable "env://TEST_RULESET_SECRET" + # local file "file:///opt/auth.json" + # secret string "val://user:password" + # optional + ruleset_secret: env://TEST_RULESET_SECRET \ No newline at end of file From 9076555e4dc9247bef71d3ea982c3d42281a79fc Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Fri, 19 Aug 2022 11:43:20 +0700 Subject: [PATCH 15/16] docs: add docs in pkg/file --- pkg/file/file.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/file/file.go b/pkg/file/file.go index bed11cae0..022cfa746 100644 --- a/pkg/file/file.go +++ b/pkg/file/file.go @@ -11,16 +11,25 @@ import ( "gopkg.in/yaml.v2" ) +// Exist checks whether a file with filename exists +// return true if exists, else false func Exist(filename string) bool { _, err := os.Stat(filename) return err == nil } +// DirExists checks whether a directory path exists +// return true if exists, else false func DirExists(path string) bool { f, err := os.Stat(path) return err == nil && f.IsDir() } +// Parse tries to read json or yaml file +// and transform the content into a struct passed +// in the 2nd argument +// File extension matters, only file with extension +// json, yaml, or yml that is parsable func Parse(filePath string, v interface{}) error { b, err := ioutil.ReadFile(filePath) if err != nil { From 619900fb8e62815a181fab53af13c1fc401a1ac9 Mon Sep 17 00:00:00 2001 From: Muhammad Abduh Date: Fri, 19 Aug 2022 11:47:39 +0700 Subject: [PATCH 16/16] docs: add more docs in pkg --- pkg/metadata/metadata.go | 5 +++++ pkg/uuid/uuid.go | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/metadata/metadata.go b/pkg/metadata/metadata.go index 57976302f..47f16f1ff 100644 --- a/pkg/metadata/metadata.go +++ b/pkg/metadata/metadata.go @@ -6,8 +6,12 @@ import ( "google.golang.org/protobuf/types/known/structpb" ) +// Metadata is a structure to store dynamic values in +// shield. it could be use as an additional information +// of a specific entity type Metadata map[string]any +// ToStructPB transforms Metadata to *structpb.Struct func (m Metadata) ToStructPB() (*structpb.Struct, error) { newMap := make(map[string]interface{}) @@ -18,6 +22,7 @@ func (m Metadata) ToStructPB() (*structpb.Struct, error) { return structpb.NewStruct(newMap) } +// Build transforms a Metadata from map[string]interface{} func Build(m map[string]interface{}) (Metadata, error) { newMap := make(Metadata) diff --git a/pkg/uuid/uuid.go b/pkg/uuid/uuid.go index aa21ce8ba..248433b73 100644 --- a/pkg/uuid/uuid.go +++ b/pkg/uuid/uuid.go @@ -2,9 +2,12 @@ package uuid import "github.com/google/uuid" -// type alias +// NewString is type alias to `github.com/google/uuid`.NewString var NewString = uuid.NewString +// IsValid returns true if passed string in uuid format +// defined by `github.com/google/uuid`.Parse +// else return false func IsValid(key string) bool { _, err := uuid.Parse(key) return err == nil