| 93 | } |
| 94 | |
| 95 | func newApp(stdout, stderr io.Writer) *cli.App { |
| 96 | // Define default file writers and prompters for go.step.sm/crypto |
| 97 | pemutil.WriteFile = fileutil.WriteFile |
| 98 | pemutil.PromptPassword = func(msg string) ([]byte, error) { |
| 99 | return ui.PromptPassword(msg) |
| 100 | } |
| 101 | jose.PromptPassword = func(msg string) ([]byte, error) { |
| 102 | return ui.PromptPassword(msg) |
| 103 | } |
| 104 | |
| 105 | // Override global framework components |
| 106 | cli.VersionPrinter = func(c *cli.Context) { |
| 107 | version.Command(c) |
| 108 | } |
| 109 | cli.AppHelpTemplate = usage.AppHelpTemplate |
| 110 | cli.SubcommandHelpTemplate = usage.SubcommandHelpTemplate |
| 111 | cli.CommandHelpTemplate = usage.CommandHelpTemplate |
| 112 | cli.HelpPrinter = usage.HelpPrinter |
| 113 | cli.FlagNamePrefixer = usage.FlagNamePrefixer |
| 114 | cli.FlagStringer = stringifyFlag |
| 115 | |
| 116 | // Configure cli app |
| 117 | app := cli.NewApp() |
| 118 | app.Name = stepAppName // "step" by default |
| 119 | app.HelpName = stepAppName // "step" by default |
| 120 | app.Usage = "plumbing for distributed systems" |
| 121 | app.Version = step.Version() |
| 122 | app.Commands = command.Retrieve() |
| 123 | app.Flags = append(app.Flags, cli.HelpFlag) |
| 124 | app.EnableBashCompletion = true |
| 125 | app.Copyright = fmt.Sprintf("(c) 2018-%d Smallstep Labs, Inc.", time.Now().Year()) |
| 126 | |
| 127 | // Flag of custom configuration flag |
| 128 | app.Flags = append(app.Flags, cli.StringFlag{ |
| 129 | Name: "config", |
| 130 | Usage: "path to the config file to use for CLI flags", |
| 131 | }) |
| 132 | |
| 133 | // Action runs on `step` or `step <command>` if the command is not enabled. |
| 134 | app.Action = func(ctx *cli.Context) error { |
| 135 | args := ctx.Args() |
| 136 | if name := args.First(); name != "" { |
| 137 | if file, err := plugin.LookPath(name); err == nil { |
| 138 | return plugin.Run(ctx, file) |
| 139 | } |
| 140 | if u := plugin.GetURL(name); u != "" { |
| 141 | //nolint:staticcheck // this is a top level error - capitalization is ok |
| 142 | return fmt.Errorf("The plugin %q was not found on this system.\nDownload it from %s", name, u) |
| 143 | } |
| 144 | return cli.ShowCommandHelp(ctx, name) |
| 145 | } |
| 146 | return cli.ShowAppHelp(ctx) |
| 147 | } |
| 148 | |
| 149 | // All non-successful output should be written to stderr |
| 150 | app.Writer = stdout |
| 151 | app.ErrWriter = stderr |
| 152 | |