github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/cmdconfig/builder.go (about) 1 package cmdconfig 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/spf13/cobra" 8 "github.com/spf13/pflag" 9 "github.com/spf13/viper" 10 "github.com/turbot/steampipe/pkg/constants" 11 "github.com/turbot/steampipe/pkg/error_helpers" 12 "github.com/turbot/steampipe/pkg/utils" 13 ) 14 15 type CmdBuilder struct { 16 cmd *cobra.Command 17 bindings map[string]*pflag.Flag 18 } 19 20 // OnCmd starts a config builder wrapping over the provided *cobra.Command 21 func OnCmd(cmd *cobra.Command) *CmdBuilder { 22 cfg := new(CmdBuilder) 23 cfg.cmd = cmd 24 cfg.bindings = map[string]*pflag.Flag{} 25 26 // we will wrap over these two function - need references to call them 27 originalPreRun := cfg.cmd.PreRun 28 cfg.cmd.PreRun = func(cmd *cobra.Command, args []string) { 29 utils.LogTime(fmt.Sprintf("cmd.%s.PreRun start", cmd.CommandPath())) 30 defer utils.LogTime(fmt.Sprintf("cmd.%s.PreRun end", cmd.CommandPath())) 31 // bind flags 32 for flagName, flag := range cfg.bindings { 33 if flag == nil { 34 // we can panic here since this is bootstrap code and not execution path specific 35 panic(fmt.Sprintf("flag for %s cannot be nil", flagName)) 36 } 37 //nolint:golint,errcheck // nil check above 38 viper.GetViper().BindPFlag(flagName, flag) 39 } 40 41 // now that we have done all the flag bindings, run the global pre run 42 // this will load up and populate the global config, init the logger and 43 // also run the daily task runner 44 preRunHook(cmd, args) 45 46 // run the original PreRun 47 if originalPreRun != nil { 48 originalPreRun(cmd, args) 49 } 50 } 51 52 originalPostRun := cfg.cmd.PostRun 53 cfg.cmd.PostRun = func(cmd *cobra.Command, args []string) { 54 utils.LogTime(fmt.Sprintf("cmd.%s.PostRun start", cmd.CommandPath())) 55 defer utils.LogTime(fmt.Sprintf("cmd.%s.PostRun end", cmd.CommandPath())) 56 // run the original PostRun 57 if originalPostRun != nil { 58 originalPostRun(cmd, args) 59 } 60 61 // run the post run 62 postRunHook(cmd, args) 63 } 64 65 // wrap over the original Run function 66 originalRun := cfg.cmd.Run 67 cfg.cmd.Run = func(cmd *cobra.Command, args []string) { 68 utils.LogTime(fmt.Sprintf("cmd.%s.Run start", cmd.CommandPath())) 69 defer utils.LogTime(fmt.Sprintf("cmd.%s.Run end", cmd.CommandPath())) 70 71 // run the original Run 72 if originalRun != nil { 73 originalRun(cmd, args) 74 } 75 } 76 77 return cfg 78 } 79 80 // AddStringFlag is a helper function to add a string flag to a command 81 func (c *CmdBuilder) AddStringFlag(name string, defaultValue string, desc string, opts ...FlagOption) *CmdBuilder { 82 c.cmd.Flags().String(name, defaultValue, desc) 83 c.bindings[name] = c.cmd.Flags().Lookup(name) 84 for _, o := range opts { 85 o(c.cmd, name, name) 86 } 87 88 return c 89 } 90 91 // AddIntFlag is a helper function to add an integer flag to a command 92 func (c *CmdBuilder) AddIntFlag(name string, defaultValue int, desc string, opts ...FlagOption) *CmdBuilder { 93 c.cmd.Flags().Int(name, defaultValue, desc) 94 c.bindings[name] = c.cmd.Flags().Lookup(name) 95 for _, o := range opts { 96 o(c.cmd, name, name) 97 } 98 return c 99 } 100 101 // AddBoolFlag ia s helper function to add a boolean flag to a command 102 func (c *CmdBuilder) AddBoolFlag(name string, defaultValue bool, desc string, opts ...FlagOption) *CmdBuilder { 103 c.cmd.Flags().Bool(name, defaultValue, desc) 104 c.bindings[name] = c.cmd.Flags().Lookup(name) 105 for _, o := range opts { 106 o(c.cmd, name, name) 107 } 108 return c 109 } 110 111 // AddCloudFlags is helper function to add the cloud flags to a command 112 func (c *CmdBuilder) AddCloudFlags() *CmdBuilder { 113 return c. 114 AddStringFlag(constants.ArgPipesHost, constants.DefaultPipesHost, "Turbot Pipes host"). 115 AddStringFlag(constants.ArgPipesToken, "", "Turbot Pipes authentication token"). 116 AddStringFlag(constants.ArgCloudHost, constants.DefaultPipesHost, "Turbot Pipes host", FlagOptions.Deprecated(constants.ArgPipesHost)). 117 AddStringFlag(constants.ArgCloudToken, "", "Turbot Pipes authentication token", FlagOptions.Deprecated(constants.ArgPipesToken)) 118 } 119 120 // AddWorkspaceDatabaseFlag is helper function to add the workspace-databse flag to a command 121 func (c *CmdBuilder) AddWorkspaceDatabaseFlag() *CmdBuilder { 122 return c. 123 AddStringFlag(constants.ArgWorkspaceDatabase, constants.DefaultWorkspaceDatabase, "Turbot Pipes workspace database") 124 } 125 126 // AddModLocationFlag is helper function to add the mod-location flag to a command 127 func (c *CmdBuilder) AddModLocationFlag() *CmdBuilder { 128 cwd, err := os.Getwd() 129 error_helpers.FailOnError(err) 130 return c. 131 AddStringFlag(constants.ArgModLocation, cwd, "Path to the workspace working directory") 132 } 133 134 // AddStringSliceFlag is a helper function to add a flag that accepts an array of strings 135 func (c *CmdBuilder) AddStringSliceFlag(name string, defaultValue []string, desc string, opts ...FlagOption) *CmdBuilder { 136 c.cmd.Flags().StringSlice(name, defaultValue, desc) 137 c.bindings[name] = c.cmd.Flags().Lookup(name) 138 for _, o := range opts { 139 o(c.cmd, name, name) 140 } 141 return c 142 } 143 144 // AddStringArrayFlag is a helper function to add a flag that accepts an array of strings 145 func (c *CmdBuilder) AddStringArrayFlag(name string, defaultValue []string, desc string, opts ...FlagOption) *CmdBuilder { 146 c.cmd.Flags().StringArray(name, defaultValue, desc) 147 c.bindings[name] = c.cmd.Flags().Lookup(name) 148 for _, o := range opts { 149 o(c.cmd, name, name) 150 } 151 return c 152 } 153 154 // AddStringMapStringFlag is a helper function to add a flag that accepts a map of strings 155 func (c *CmdBuilder) AddStringMapStringFlag(name string, defaultValue map[string]string, desc string, opts ...FlagOption) *CmdBuilder { 156 c.cmd.Flags().StringToString(name, defaultValue, desc) 157 c.bindings[name] = c.cmd.Flags().Lookup(name) 158 for _, o := range opts { 159 o(c.cmd, name, name) 160 } 161 return c 162 } 163 164 func (c *CmdBuilder) AddVarFlag(value pflag.Value, name string, usage string, opts ...FlagOption) *CmdBuilder { 165 c.cmd.Flags().Var(value, name, usage) 166 167 c.bindings[name] = c.cmd.Flags().Lookup(name) 168 for _, o := range opts { 169 o(c.cmd, name, name) 170 } 171 172 // 173 return c 174 }