Skip to content

Commit c791bbf

Browse files
authored
Merge pull request #1426 from smallstep/herman/testscript
Refactor CLI to make it testable using `testscript`
2 parents 9cce28a + 279e638 commit c791bbf

44 files changed

Lines changed: 1953 additions & 1947 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Makefile

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,6 @@ race:
157157

158158
.PHONY: test race
159159

160-
integrate: integration
161-
162-
integration: build
163-
$Q $(CGO_OVERRIDE) gotestsum -- -tags=integration ./integration/...
164-
165-
.PHONY: integrate integration
166-
167160
#########################################
168161
# Linting
169162
#########################################

cmd/step/main.go

Lines changed: 6 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,12 @@
11
package main
22

33
import (
4-
"errors"
5-
"fmt"
6-
"io"
74
"os"
8-
"reflect"
9-
"regexp"
10-
"strings"
11-
"time"
12-
13-
"github.com/urfave/cli"
145

156
"github.com/smallstep/certificates/ca"
16-
"github.com/smallstep/cli-utils/command"
177
"github.com/smallstep/cli-utils/step"
18-
"github.com/smallstep/cli-utils/ui"
19-
"github.com/smallstep/cli-utils/usage"
20-
"go.step.sm/crypto/jose"
21-
"go.step.sm/crypto/pemutil"
22-
23-
"github.com/smallstep/cli/command/version"
24-
"github.com/smallstep/cli/internal/plugin"
25-
"github.com/smallstep/cli/utils"
26-
27-
// Enabled cas interfaces.
28-
_ "github.com/smallstep/certificates/cas/cloudcas"
29-
_ "github.com/smallstep/certificates/cas/softcas"
30-
_ "github.com/smallstep/certificates/cas/stepcas"
318

32-
// Enabled commands
33-
_ "github.com/smallstep/cli/command/api"
34-
_ "github.com/smallstep/cli/command/base64"
35-
_ "github.com/smallstep/cli/command/beta"
36-
_ "github.com/smallstep/cli/command/ca"
37-
_ "github.com/smallstep/cli/command/certificate"
38-
_ "github.com/smallstep/cli/command/completion"
39-
_ "github.com/smallstep/cli/command/context"
40-
_ "github.com/smallstep/cli/command/crl"
41-
_ "github.com/smallstep/cli/command/crypto"
42-
_ "github.com/smallstep/cli/command/fileserver"
43-
_ "github.com/smallstep/cli/command/oauth"
44-
_ "github.com/smallstep/cli/command/path"
45-
_ "github.com/smallstep/cli/command/ssh"
9+
"github.com/smallstep/cli/internal/cmd"
4610
)
4711

4812
// Version is set by an LDFLAG at build time representing the git tag or commit
@@ -53,143 +17,15 @@ var Version = "N/A"
5317
// the time of build
5418
var BuildTime = "N/A"
5519

20+
// AppName is the name of the binary. Defaults to "step" if not set.
21+
var AppName = ""
22+
5623
func init() {
5724
step.Set("Smallstep CLI", Version, BuildTime)
5825
ca.UserAgent = step.Version()
26+
cmd.SetName(AppName)
5927
}
6028

6129
func main() {
62-
// initialize step environment.
63-
if err := step.Init(); err != nil {
64-
fmt.Fprintln(os.Stderr, err.Error())
65-
os.Exit(1)
66-
}
67-
68-
defer panicHandler()
69-
70-
// create new instance of app
71-
app := newApp(os.Stdout, os.Stderr)
72-
73-
if err := app.Run(os.Args); err != nil {
74-
var messenger interface {
75-
Message() string
76-
}
77-
if errors.As(err, &messenger) {
78-
if os.Getenv("STEPDEBUG") == "1" {
79-
fmt.Fprintf(os.Stderr, "%+v\n\n%s", err, messenger.Message())
80-
} else {
81-
fmt.Fprintln(os.Stderr, messenger.Message())
82-
fmt.Fprintln(os.Stderr, "Re-run with STEPDEBUG=1 for more info.")
83-
}
84-
} else {
85-
if os.Getenv("STEPDEBUG") == "1" {
86-
fmt.Fprintf(os.Stderr, "%+v\n", err)
87-
} else {
88-
fmt.Fprintln(os.Stderr, err)
89-
}
90-
}
91-
//nolint:gocritic // ignore exitAfterDefer error because the defer is required for recovery.
92-
os.Exit(1)
93-
}
94-
}
95-
96-
func newApp(stdout, stderr io.Writer) *cli.App {
97-
// Define default file writers and prompters for go.step.sm/crypto
98-
pemutil.WriteFile = utils.WriteFile
99-
pemutil.PromptPassword = func(msg string) ([]byte, error) {
100-
return ui.PromptPassword(msg)
101-
}
102-
jose.PromptPassword = func(msg string) ([]byte, error) {
103-
return ui.PromptPassword(msg)
104-
}
105-
106-
// Override global framework components
107-
cli.VersionPrinter = func(c *cli.Context) {
108-
version.Command(c)
109-
}
110-
cli.AppHelpTemplate = usage.AppHelpTemplate
111-
cli.SubcommandHelpTemplate = usage.SubcommandHelpTemplate
112-
cli.CommandHelpTemplate = usage.CommandHelpTemplate
113-
cli.HelpPrinter = usage.HelpPrinter
114-
cli.FlagNamePrefixer = usage.FlagNamePrefixer
115-
cli.FlagStringer = stringifyFlag
116-
117-
// Configure cli app
118-
app := cli.NewApp()
119-
app.Name = "step"
120-
app.HelpName = "step"
121-
app.Usage = "plumbing for distributed systems"
122-
app.Version = step.Version()
123-
app.Commands = command.Retrieve()
124-
app.Flags = append(app.Flags, cli.HelpFlag)
125-
app.EnableBashCompletion = true
126-
app.Copyright = fmt.Sprintf("(c) 2018-%d Smallstep Labs, Inc.", time.Now().Year())
127-
128-
// Flag of custom configuration flag
129-
app.Flags = append(app.Flags, cli.StringFlag{
130-
Name: "config",
131-
Usage: "path to the config file to use for CLI flags",
132-
})
133-
134-
// Action runs on `step` or `step <command>` if the command is not enabled.
135-
app.Action = func(ctx *cli.Context) error {
136-
args := ctx.Args()
137-
if name := args.First(); name != "" {
138-
if file, err := plugin.LookPath(name); err == nil {
139-
return plugin.Run(ctx, file)
140-
}
141-
if u := plugin.GetURL(name); u != "" {
142-
//nolint:staticcheck // this is a top level error - capitalization is ok
143-
return fmt.Errorf("The plugin %q was not found on this system.\nDownload it from %s", name, u)
144-
}
145-
return cli.ShowCommandHelp(ctx, name)
146-
}
147-
return cli.ShowAppHelp(ctx)
148-
}
149-
150-
// All non-successful output should be written to stderr
151-
app.Writer = stdout
152-
app.ErrWriter = stderr
153-
154-
return app
155-
}
156-
157-
func panicHandler() {
158-
if r := recover(); r != nil {
159-
if os.Getenv("STEPDEBUG") == "1" {
160-
fmt.Fprintf(os.Stderr, "%s\n", step.Version())
161-
fmt.Fprintf(os.Stderr, "Release Date: %s\n\n", step.ReleaseDate())
162-
panic(r)
163-
}
164-
165-
fmt.Fprintln(os.Stderr, "Something unexpected happened.")
166-
fmt.Fprintln(os.Stderr, "If you want to help us debug the problem, please run:")
167-
fmt.Fprintf(os.Stderr, "STEPDEBUG=1 %s\n", strings.Join(os.Args, " "))
168-
fmt.Fprintln(os.Stderr, "and send the output to [email protected]")
169-
os.Exit(2)
170-
}
171-
}
172-
173-
func flagValue(f cli.Flag) reflect.Value {
174-
fv := reflect.ValueOf(f)
175-
for fv.Kind() == reflect.Ptr {
176-
fv = reflect.Indirect(fv)
177-
}
178-
return fv
179-
}
180-
181-
var placeholderString = regexp.MustCompile(`<.*?>`)
182-
183-
func stringifyFlag(f cli.Flag) string {
184-
fv := flagValue(f)
185-
usg := fv.FieldByName("Usage").String()
186-
placeholder := placeholderString.FindString(usg)
187-
if placeholder == "" {
188-
switch f.(type) {
189-
case cli.BoolFlag, cli.BoolTFlag:
190-
default:
191-
placeholder = "<value>"
192-
}
193-
}
194-
return cli.FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder) + "\t" + usg
30+
os.Exit(cmd.Run())
19531
}

docs/local-development.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,6 @@ Run the unit tests:
5252
make test
5353
```
5454

55-
#### Integration Tests
56-
57-
Run the integration tests:
58-
59-
```
60-
make integration
61-
```
62-
6355
#### And coding style tests
6456

6557
The currently enabled linters are defined in our shared [golangci-lint config](https://raw.githubusercontent.com/smallstep/workflows/master/.golangci.yml)

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/manifoldco/promptui v0.9.0
1616
github.com/pkg/errors v0.9.1
1717
github.com/pquerna/otp v1.5.0
18+
github.com/rogpeppe/go-internal v1.13.1
1819
github.com/slackhq/nebula v1.9.5
1920
github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262
2021
github.com/smallstep/certificates v0.28.3
@@ -137,6 +138,7 @@ require (
137138
golang.org/x/sync v0.15.0 // indirect
138139
golang.org/x/text v0.26.0 // indirect
139140
golang.org/x/time v0.11.0 // indirect
141+
golang.org/x/tools v0.33.0 // indirect
140142
google.golang.org/api v0.234.0 // indirect
141143
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect
142144
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
473473
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
474474
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
475475
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
476+
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
477+
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
476478
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
477479
google.golang.org/api v0.234.0 h1:d3sAmYq3E9gdr2mpmiWGbm9pHsA/KJmyiLkwKfHBqU4=
478480
google.golang.org/api v0.234.0/go.mod h1:QpeJkemzkFKe5VCE/PMv7GsUfn9ZF+u+q1Q7w6ckxTg=

integration/README.md

Lines changed: 0 additions & 13 deletions
This file was deleted.

integration/certificate_sign_test.go

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)