Skip to content

Commit 91cc689

Browse files
committed
v0.0.36: add cert management choice and misc refinements
1 parent 96f08cc commit 91cc689

File tree

28 files changed

+376
-207
lines changed

28 files changed

+376
-207
lines changed

api/api.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"net/http"
1313
"net/url"
1414
"os/exec"
15-
"runtime"
1615
"strings"
1716

1817
"github.com/anchordotdev/cli"
@@ -66,7 +65,7 @@ func NewClient(cfg *cli.Config) (*Session, error) {
6665
if apiToken, err = kr.Get(keyring.APIToken); err == keyring.ErrNotFound {
6766
return anc, ErrSignedOut
6867
}
69-
if err != nil && gnomeKeyringMissing() {
68+
if err != nil && gnomeKeyringMissing(cfg) {
7069
return anc, ErrGnomeKeyringRequired
7170
}
7271

@@ -390,8 +389,8 @@ const NotFoundErr = StatusCodeError(http.StatusNotFound)
390389
func (err StatusCodeError) StatusCode() int { return int(err) }
391390
func (err StatusCodeError) Error() string { return fmt.Sprintf("unexpected %d status response", err) }
392391

393-
func gnomeKeyringMissing() bool {
394-
if runtime.GOOS != "linux" {
392+
func gnomeKeyringMissing(cfg *cli.Config) bool {
393+
if cfg.GOOS() != "linux" {
395394
return false
396395
}
397396
if path, _ := exec.LookPath("gnome-keyring-daemon"); path != "" {

auth/testdata/TestCmdAuth/--help.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Manage Anchor.dev Authentication
22

33
Usage:
4-
anchor auth <subcommand> [flags]
4+
anchor auth [flags]
55
anchor auth [command]
66

77
Available Commands:

auth/testdata/TestCmdAuth/auth.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Manage Anchor.dev Authentication
22

33
Usage:
4-
anchor auth <subcommand> [flags]
4+
anchor auth [flags]
55
anchor auth [command]
66

77
Available Commands:

cert/models/provision.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ func (m *Provision) View() string {
5555
fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf("Wrote certificate to %s", ui.Emphasize(m.certFile))))
5656
fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf("Wrote chain to %s", ui.Emphasize(m.chainFile))))
5757
fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf("Wrote key to %s", ui.Emphasize(m.keyFile))))
58-
fmt.Fprintln(&b, ui.StepHint("You can use these certificate files to manually configure your application and"))
59-
fmt.Fprintln(&b, ui.StepHint("start using HTTPS in your development environment."))
58+
59+
fmt.Fprintln(&b, ui.StepHint("To use these certificates please reference your language and/or framework docs."))
60+
fmt.Fprintln(&b, ui.StepHint("When these certificates expire, rerun `anchor lcl mkcert` to generate new ones."))
6061

6162
return b.String()
6263
}

cli.go

Lines changed: 1 addition & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66
"go/build"
7-
"io/fs"
87
"net/url"
98
"os"
109
"regexp"
@@ -49,89 +48,6 @@ func VersionString() string {
4948
return fmt.Sprintf("%s (%s/%s) Commit: %s BuildDate: %s", Version.Version, Version.Os, Version.Arch, Version.Commit, Version.Date)
5049
}
5150

52-
type Config struct {
53-
JSON bool `desc:"Only print JSON output to STDOUT." flag:"json,j" env:"JSON_OUTPUT" toml:"json-output"`
54-
NonInteractive bool `desc:"Run without ever asking for user input." flag:"non-interactive,n" env:"NON_INTERACTIVE" toml:"non-interactive"`
55-
Verbose bool `desc:"Verbose output." flag:"verbose,v" env:"VERBOSE" toml:"verbose"`
56-
57-
AnchorURL string `default:"https://anchor.dev" desc:"TODO" flag:"host" env:"ANCHOR_HOST" toml:"anchor-host"`
58-
59-
API struct {
60-
URL string `default:"https://api.anchor.dev/v0" desc:"Anchor API endpoint URL." flag:"api-url,u" env:"API_URL" json:"api_url" toml:"api-url"`
61-
Token string `desc:"Anchor API personal access token (PAT)." flag:"api-token,t" env:"API_TOKEN" json:"api_token" toml:"token"`
62-
}
63-
64-
Lcl struct {
65-
Service string `desc:"Name for lcl.host diagnostic service." flag:"service" env:"SERVICE" json:"service" toml:"service"`
66-
Subdomain string `desc:"Subdomain for lcl.host diagnostic service." flag:"subdomain" env:"SUBDOMAIN" json:"subdomain" toml:"subdomain"`
67-
68-
DiagnosticAddr string `default:":4433" desc:"Local server address" flag:"addr,a" env:"ADDR" json:"address" toml:"address"`
69-
LclHostURL string `default:"https://lcl.host" env:"LCL_HOST_URL"`
70-
71-
Audit struct {
72-
} `cmd:"audit"`
73-
74-
Clean struct {
75-
} `cmd:"clean"`
76-
77-
Config struct {
78-
} `cmd:"config"`
79-
80-
MkCert struct {
81-
Domains []string `flag:"domains"`
82-
SubCa string `flag:"subca"`
83-
} `cmd:"mkcert"`
84-
85-
Setup struct {
86-
Language string `desc:"Language to use for integrating Anchor." flag:"language" json:"language" toml:"language"`
87-
} `cmd:"setup"`
88-
} `cmd:"lcl"`
89-
90-
Test struct {
91-
Browserless bool `desc:"run as though browserless"`
92-
SkipRunE bool `desc:"skip RunE for testing purposes"`
93-
}
94-
95-
Trust struct {
96-
Org string `desc:"organization" flag:"org,o" env:"ORG" json:"org" toml:"org"`
97-
Realm string `desc:"realm" flag:"realm,r" env:"REALM" json:"realm" toml:"realm"`
98-
99-
NoSudo bool `desc:"Disable sudo prompts." flag:"no-sudo" env:"NO_SUDO" toml:"no-sudo"`
100-
101-
MockMode bool `env:"ANCHOR_CLI_TRUSTSTORE_MOCK_MODE"`
102-
103-
Stores []string `default:"[system,nss,homebrew]" desc:"trust stores" flag:"trust-stores" env:"TRUST_STORES" toml:"trust-stores"`
104-
105-
Audit struct{} `cmd:"audit"`
106-
107-
Clean struct {
108-
States []string `default:"[expired]" desc:"cert state(s)" flag:"cert-states" env:"CERT_STATES" toml:"cert-states"`
109-
} `cmd:"clean"`
110-
} `cmd:"trust"`
111-
112-
User struct {
113-
Auth struct {
114-
SignIn struct{} `cmd:"signin"`
115-
116-
SignOut struct{} `cmd:"signout"`
117-
118-
WhoAmI struct{} `cmd:"whoami"`
119-
} `cmd:"auth"`
120-
} `group:"user,user management" toml:"user"`
121-
122-
Keyring struct {
123-
MockMode bool `env:"ANCHOR_CLI_KEYRING_MOCK_MODE"`
124-
}
125-
126-
Version struct{} `cmd:"version"`
127-
128-
// values used for testing
129-
130-
GOOS string `desc:"change OS identifier in tests"`
131-
ProcFS fs.FS `desc:"change the proc filesystem in tests"`
132-
Timestamp time.Time `desc:"timestamp to use/display in tests"`
133-
}
134-
13551
type UI struct {
13652
RunTUI func(context.Context, *ui.Driver) error
13753
}
@@ -228,12 +144,7 @@ func ReportError(ctx context.Context, drv *ui.Driver, cmd *cobra.Command, args [
228144
fmt.Fprintf(&body, "**Version:** `%s`\n", VersionString())
229145
fmt.Fprintf(&body, "**Arguments:** `[%s]`\n", strings.Join(args, ", "))
230146
fmt.Fprintf(&body, "**Flags:** `[%s]`\n", strings.Join(flags, ", "))
231-
232-
timestamp := cfg.Timestamp
233-
if timestamp.IsZero() {
234-
timestamp = time.Now().UTC()
235-
}
236-
fmt.Fprintf(&body, "**Timestamp:** `%s`\n", timestamp.Format(time.RFC3339Nano))
147+
fmt.Fprintf(&body, "**Timestamp:** `%s`\n", cfg.Timestamp().Format(time.RFC3339Nano))
237148
if stack != "" {
238149
fmt.Fprintf(&body, "**Stack:**\n```\n%s\n```\n", normalizeStack(stack))
239150
}

cli_test.go

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,13 @@ func TestError(t *testing.T) {
7373
ctx, cancel := context.WithCancel(context.Background())
7474
defer cancel()
7575

76-
var err error
77-
cfg := cli.Config{}
78-
cfg.NonInteractive = true
79-
cfg.Test.Browserless = true
80-
cfg.Timestamp = Timestamp
81-
if err != nil {
82-
t.Fatal(err)
83-
}
84-
ctx = cli.ContextWithConfig(ctx, &cfg)
76+
ctx = cli.ContextWithConfig(ctx, &cli.Config{
77+
NonInteractive: true,
78+
Test: cli.ConfigTest{
79+
Browserless: true,
80+
Timestamp: Timestamp,
81+
},
82+
})
8583

8684
t.Run(fmt.Sprintf("golden-%s", testTag()), func(t *testing.T) {
8785
var returnedError error
@@ -124,15 +122,13 @@ func TestPanic(t *testing.T) {
124122
ctx, cancel := context.WithCancel(context.Background())
125123
defer cancel()
126124

127-
var err error
128-
cfg := cli.Config{}
129-
cfg.NonInteractive = true
130-
cfg.Test.Browserless = true
131-
cfg.Timestamp = Timestamp
132-
if err != nil {
133-
t.Fatal(err)
134-
}
135-
ctx = cli.ContextWithConfig(ctx, &cfg)
125+
ctx = cli.ContextWithConfig(ctx, &cli.Config{
126+
NonInteractive: true,
127+
Test: cli.ConfigTest{
128+
Browserless: true,
129+
Timestamp: Timestamp,
130+
},
131+
})
136132

137133
t.Run(fmt.Sprintf("golden-%s", testTag()), func(t *testing.T) {
138134
var returnedError error

cmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ var rootDef = CmdDef{
4040
{
4141
Name: "auth",
4242

43-
Use: "auth <subcommand> [flags]",
43+
Use: "auth [flags]",
4444
Args: cobra.NoArgs,
4545
Short: "Manage Anchor.dev Authentication",
4646

config.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package cli
2+
3+
import (
4+
"io/fs"
5+
"os"
6+
"runtime"
7+
"time"
8+
)
9+
10+
type Config struct {
11+
JSON bool `desc:"Only print JSON output to STDOUT." flag:"json,j" env:"JSON_OUTPUT" toml:"json-output"`
12+
NonInteractive bool `desc:"Run without ever asking for user input." flag:"non-interactive,n" env:"NON_INTERACTIVE" toml:"non-interactive"`
13+
Verbose bool `desc:"Verbose output." flag:"verbose,v" env:"VERBOSE" toml:"verbose"`
14+
15+
AnchorURL string `default:"https://anchor.dev" desc:"TODO" flag:"host" env:"ANCHOR_HOST" toml:"anchor-host"`
16+
17+
API struct {
18+
URL string `default:"https://api.anchor.dev/v0" desc:"Anchor API endpoint URL." flag:"api-url,u" env:"API_URL" json:"api_url" toml:"api-url"`
19+
Token string `desc:"Anchor API personal access token (PAT)." flag:"api-token,t" env:"API_TOKEN" json:"api_token" toml:"token"`
20+
}
21+
22+
Lcl struct {
23+
Service string `desc:"Name for lcl.host diagnostic service." flag:"service" env:"SERVICE" json:"service" toml:"service"`
24+
Subdomain string `desc:"Subdomain for lcl.host diagnostic service." flag:"subdomain" env:"SUBDOMAIN" json:"subdomain" toml:"subdomain"`
25+
26+
DiagnosticAddr string `default:":4433" desc:"Local server address" flag:"addr,a" env:"ADDR" json:"address" toml:"address"`
27+
LclHostURL string `default:"https://lcl.host" env:"LCL_HOST_URL"`
28+
29+
Audit struct {
30+
} `cmd:"audit"`
31+
32+
Clean struct {
33+
} `cmd:"clean"`
34+
35+
Config struct {
36+
} `cmd:"config"`
37+
38+
MkCert struct {
39+
Domains []string `flag:"domains"`
40+
SubCa string `flag:"subca"`
41+
} `cmd:"mkcert"`
42+
43+
Setup struct {
44+
Language string `desc:"Language to use for integrating Anchor." flag:"language" json:"language" toml:"language"`
45+
Method string `desc:"Integration method for certificates."`
46+
} `cmd:"setup"`
47+
} `cmd:"lcl"`
48+
49+
Service struct {
50+
Probe struct {
51+
Name string `desc:"service name"`
52+
53+
Org string `desc:"organization" flag:"org,o" env:"ORG" json:"org" toml:"org"`
54+
Realm string `desc:"realm" flag:"realm,r" env:"REALM" json:"realm" toml:"realm"`
55+
} `cmd:"probe"`
56+
} `cmd:"service"`
57+
58+
Trust struct {
59+
Org string `desc:"organization" flag:"org,o" env:"ORG" json:"org" toml:"org"`
60+
Realm string `desc:"realm" flag:"realm,r" env:"REALM" json:"realm" toml:"realm"`
61+
62+
NoSudo bool `desc:"Disable sudo prompts." flag:"no-sudo" env:"NO_SUDO" toml:"no-sudo"`
63+
64+
MockMode bool `env:"ANCHOR_CLI_TRUSTSTORE_MOCK_MODE"`
65+
66+
Stores []string `default:"[system,nss,homebrew]" desc:"trust stores" flag:"trust-stores" env:"TRUST_STORES" toml:"trust-stores"`
67+
68+
Audit struct{} `cmd:"audit"`
69+
70+
Clean struct {
71+
States []string `default:"[expired]" desc:"cert state(s)" flag:"cert-states" env:"CERT_STATES" toml:"cert-states"`
72+
} `cmd:"clean"`
73+
} `cmd:"trust"`
74+
75+
User struct {
76+
Auth struct {
77+
SignIn struct{} `cmd:"signin"`
78+
79+
SignOut struct{} `cmd:"signout"`
80+
81+
WhoAmI struct{} `cmd:"whoami"`
82+
} `cmd:"auth"`
83+
} `group:"user,user management" toml:"user"`
84+
85+
Keyring struct {
86+
MockMode bool `env:"ANCHOR_CLI_KEYRING_MOCK_MODE"`
87+
}
88+
89+
Version struct{} `cmd:"version"`
90+
91+
Test ConfigTest
92+
}
93+
94+
// values used for testing
95+
type ConfigTest struct {
96+
Browserless bool `desc:"run as though browserless"`
97+
GOOS string `desc:"change OS identifier in tests"`
98+
ProcFS fs.FS `desc:"change the proc filesystem in tests"`
99+
SkipRunE bool `desc:"skip RunE for testing purposes"`
100+
Timestamp time.Time `desc:"timestamp to use/display in tests"`
101+
}
102+
103+
func (c Config) GOOS() string {
104+
if goos := c.Test.GOOS; goos != "" {
105+
return goos
106+
}
107+
return runtime.GOOS
108+
}
109+
110+
func (c Config) ProcFS() fs.FS {
111+
if procFS := c.Test.ProcFS; procFS != nil {
112+
return procFS
113+
}
114+
return os.DirFS("/proc")
115+
}
116+
117+
func (c Config) Timestamp() time.Time {
118+
if timestamp := c.Test.Timestamp; !timestamp.IsZero() {
119+
return timestamp
120+
}
121+
return time.Now().UTC()
122+
}

lcl/lcl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var CmdLcl = cli.NewCmd[Command](cli.CmdRoot, "lcl", func(cmd *cobra.Command) {
2929

3030
// setup
3131
cmd.Flags().StringVar(&cfg.Lcl.Setup.Language, "language", "", "Language to integrate with Anchor.")
32+
cmd.Flags().StringVar(&cfg.Lcl.Setup.Method, "method", "", "Integration method for certificates.")
3233
})
3334

3435
type Command struct {

lcl/lcl_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ func TestCmdLcl(t *testing.T) {
8484
cfg := cmdtest.TestCfg(t, CmdLcl, "--language", "ruby")
8585
require.Equal(t, "ruby", cfg.Lcl.Setup.Language)
8686
})
87+
88+
t.Run("--method anchor", func(t *testing.T) {
89+
cfg := cmdtest.TestCfg(t, CmdLcl, "--method", "anchor")
90+
require.Equal(t, "anchor", cfg.Lcl.Setup.Method)
91+
})
8792
}
8893

8994
func TestLcl(t *testing.T) {
@@ -223,6 +228,14 @@ func TestLcl(t *testing.T) {
223228
Type: tea.KeyEnter,
224229
})
225230

231+
uitest.WaitForGoldenContains(t, drv, errc,
232+
"? What certificate management method?",
233+
)
234+
235+
tm.Send(tea.KeyMsg{
236+
Type: tea.KeyEnter,
237+
})
238+
226239
t.Skip("Pending workaround for consistent setup guide port value")
227240

228241
uitest.WaitForGoldenContains(t, drv, errc,

0 commit comments

Comments
 (0)