From caba8dc9cf6edb24bdbbe2bcb6309d13816146b0 Mon Sep 17 00:00:00 2001 From: geemus Date: Tue, 30 Jul 2024 14:47:03 +0000 Subject: [PATCH] v0.0.39 multi-org lcl; misc fixes and refinements --- api/api.go | 186 ++-- api/apitest/apitest.go | 36 +- api/openapi.gen.go | 2 +- api/openapi.go | 26 + auth/signin_test.go | 3 - auth/testdata/TestSignout/signed-out.golden | 2 + ...gned-in-but-out-of-date-cli-release.golden | 6 +- auth/testdata/TestWhoAmI/signed-in.golden | 3 + auth/testdata/TestWhoAmI/signed-out.golden | 3 + cert/models/provision.go | 17 +- cert/provision.go | 18 +- cli.go | 22 + cmd.go | 10 +- component/component_test.go | 24 + component/fetcher.go | 32 + component/models/selectors.go | 127 ++- component/selector.go | 86 ++ .../{selectors_test.go => selector_test.go} | 94 +- component/selectors.go | 146 --- .../testdata/TestSelector/orgs_double.golden | 2 +- .../testdata/TestSelector/orgs_empty.golden | 8 + .../testdata/TestSelector/orgs_solo.golden | 4 +- config.go | 4 +- diagnostic/server.go | 34 +- go.mod | 21 +- go.sum | 42 +- lcl/config_test.go | 8 +- lcl/lcl.go | 80 +- lcl/lcl_test.go | 35 +- lcl/mkcert.go | 179 +++- lcl/mkcert_test.go | 19 +- lcl/models/audit.go | 2 +- lcl/models/clean.go | 17 +- lcl/models/config.go | 2 +- lcl/models/lcl.go | 4 +- lcl/models/setup.go | 14 +- lcl/provision.go | 18 +- lcl/setup.go | 189 +++- lcl/setup_test.go | 254 ++++- lcl/testdata/TestAudit/basics.golden | 16 +- lcl/testdata/TestClean/basics.golden | 10 +- lcl/testdata/TestCmdLcl/--help.golden | 3 + lcl/testdata/TestCmdLclMkCert/--help.golden | 4 +- lcl/testdata/TestCmdLclSetup/--help.golden | 3 + lcl/testdata/TestLclConfig/basics.golden | 69 +- .../TestSetup/automated-basics.golden | 166 ++++ .../create-service-automated-basics.golden | 288 ++++++ .../create-service-manual-basics.golden | 387 ++++++++ .../create-service-with-custom-domain.golden | 934 ++++++++++++++++++ ...ate-service-with-parameterized-name.golden | 387 ++++++++ .../existing-service-basics-unix.golden | 312 ++++++ .../existing-service-basics-windows.golden | 314 ++++++ lcl/testdata/TestSetup/manual-basics.golden | 222 +++++ service/env.go | 209 ++-- service/env_test.go | 81 +- service/models/env.go | 71 +- .../TestServiceEnv/basics_display.golden | 144 +++ .../TestServiceEnv/basics_dotenv.golden | 89 +- ..._clipboard.golden => basics_export.golden} | 82 +- testdata/TestError/golden-unix.golden | 8 +- testdata/TestError/golden-windows.golden | 8 +- testdata/TestPanic/golden-unix.golden | 8 +- testdata/TestPanic/golden-windows.golden | 8 +- trust/clean.go | 20 +- trust/models/audit.go | 2 +- trust/models/clean.go | 16 +- trust/models/trust.go | 2 +- .../expected,_missing,_and_extra_CAs.golden | 13 +- trust/testdata/TestClean/basics.golden | 10 +- trust/testdata/TestTrust/basics-unix.golden | 48 +- .../testdata/TestTrust/basics-windows.golden | 48 +- trust/testdata/TestTrust/noop.golden | 30 +- trust/testdata/TestTrust/wsl-vm.golden | 51 +- trust/trust.go | 91 +- trust/trust_test.go | 20 +- truststore/brew.go | 2 +- truststore/brew_test.go | 4 +- truststore/errors.go | 8 +- truststore/platform_darwin.go | 1 - truststore/platform_linux.go | 5 +- truststore/platform_windows.go | 4 +- ui/styles.go | 4 +- ui/uitest/uitest.go | 17 +- version/version.go | 6 +- 84 files changed, 5122 insertions(+), 882 deletions(-) create mode 100644 api/openapi.go create mode 100644 component/component_test.go create mode 100644 component/fetcher.go create mode 100644 component/selector.go rename component/{selectors_test.go => selector_test.go} (55%) delete mode 100644 component/selectors.go create mode 100644 component/testdata/TestSelector/orgs_empty.golden create mode 100644 lcl/testdata/TestSetup/automated-basics.golden create mode 100644 lcl/testdata/TestSetup/create-service-automated-basics.golden create mode 100644 lcl/testdata/TestSetup/create-service-manual-basics.golden create mode 100644 lcl/testdata/TestSetup/create-service-with-custom-domain.golden create mode 100644 lcl/testdata/TestSetup/create-service-with-parameterized-name.golden create mode 100644 lcl/testdata/TestSetup/existing-service-basics-unix.golden create mode 100644 lcl/testdata/TestSetup/existing-service-basics-windows.golden create mode 100644 lcl/testdata/TestSetup/manual-basics.golden create mode 100644 service/testdata/TestServiceEnv/basics_display.golden rename service/testdata/TestServiceEnv/{basics_clipboard.golden => basics_export.golden} (61%) diff --git a/api/api.go b/api/api.go index 685432d..301cb74 100644 --- a/api/api.go +++ b/api/api.go @@ -42,19 +42,18 @@ type Session struct { func NewClient(ctx context.Context, cfg *cli.Config) (*Session, error) { anc := &Session{ Client: &http.Client{ - Transport: urlRewriter{ - RoundTripper: responseChecker{ - RoundTripper: userAgentSetter{ - RoundTripper: preferSetter{ - cfg: cfg, - RoundTripper: new(http.Transport), - }, - }, + Transport: Middlewares{ + urlRewriter{ + url: cfg.API.URL, }, - URL: cfg.API.URL, - }, + responseChecker, + userAgentSetter, + preferSetter{ + cfg: cfg, + }, + autoRetrier, + }.RoundTripper(new(http.Transport)), }, - cfg: cfg, } @@ -271,12 +270,12 @@ func getOrgServicesPath(orgSlug string) string { return "/orgs/" + url.QueryEscape(orgSlug) + "/services" } -func (s *Session) GetOrgServices(ctx context.Context, orgSlug string) ([]Service, error) { +func (s *Session) GetOrgServices(ctx context.Context, orgSlug string, filters ...Filter[Service]) ([]Service, error) { var svc Services if err := s.get(ctx, getOrgServicesPath(orgSlug), &svc); err != nil { return nil, err } - return svc.Items, nil + return Filters[Service](filters).Apply(svc.Items), nil } func getServicePath(orgSlug, serviceSlug string) string { @@ -361,8 +360,33 @@ func (r basicAuther) RoundTrip(req *http.Request) (*http.Response, error) { return r.RoundTripper.RoundTrip(req) } -type responseChecker struct { - http.RoundTripper +type Middleware interface { + RoundTripper(next http.RoundTripper) http.RoundTripper +} + +type Middlewares []Middleware + +func (m Middlewares) RoundTripper(tport *http.Transport) http.RoundTripper { + rm := slices.Clone(m) + slices.Reverse(rm) + + var next http.RoundTripper = tport + for _, mw := range rm { + next = mw.RoundTripper(next) + } + return next +} + +type RoundTripFunc func(*http.Request) (*http.Response, error) + +func (fn RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return fn(req) +} + +type MiddlewareFunc func(next http.RoundTripper) http.RoundTripper + +func (fn MiddlewareFunc) RoundTripper(next http.RoundTripper) http.RoundTripper { + return fn(next) } var jsonMediaTypes = mediaTypes{ @@ -370,81 +394,98 @@ var jsonMediaTypes = mediaTypes{ "application/problem+json", } -func (r responseChecker) RoundTrip(req *http.Request) (*http.Response, error) { - res, err := r.RoundTripper.RoundTrip(req) - if err != nil { - return nil, fmt.Errorf("request error %s %s: %w", req.Method, req.URL.Path, err) - } +var responseChecker = MiddlewareFunc(func(next http.RoundTripper) http.RoundTripper { + return RoundTripFunc(func(req *http.Request) (*http.Response, error) { + res, err := next.RoundTrip(req) + if err != nil { + return nil, fmt.Errorf("request error %s %s: %w", req.Method, req.URL.Path, err) + } - requestId := res.Header.Get("X-Request-Id") + requestId := res.Header.Get("X-Request-Id") - switch res.StatusCode { - case http.StatusForbidden: - return nil, ErrSignedOut - case http.StatusInternalServerError: - return nil, fmt.Errorf("request [%s] failed: 500 Internal Server Error", requestId) - } - if contentType := res.Header.Get("Content-Type"); !jsonMediaTypes.Matches(contentType) { - return nil, fmt.Errorf("request [%s]: %d response, expected json content-type, got: %q", requestId, res.StatusCode, contentType) - } - return res, nil -} + switch res.StatusCode { + case http.StatusForbidden: + return nil, ErrSignedOut + case http.StatusInternalServerError: + return nil, fmt.Errorf("request [%s] failed: 500 Internal Server Error", requestId) + } + if contentType := res.Header.Get("Content-Type"); !jsonMediaTypes.Matches(contentType) { + return nil, fmt.Errorf("request [%s]: %d response, expected json content-type, got: %q", requestId, res.StatusCode, contentType) + } + return res, nil + }) +}) type urlRewriter struct { - http.RoundTripper - - URL string + url string } -func (r urlRewriter) RoundTrip(req *http.Request) (*http.Response, error) { - u, err := url.Parse(r.URL) - if err != nil { - return nil, err - } - req.URL = u.JoinPath(req.URL.Path) +func (r urlRewriter) RoundTripper(next http.RoundTripper) http.RoundTripper { + return RoundTripFunc(func(req *http.Request) (*http.Response, error) { + u, err := url.Parse(r.url) + if err != nil { + return nil, err + } + req.URL = u.JoinPath(req.URL.Path) - return r.RoundTripper.RoundTrip(req) + return next.RoundTrip(req) + }) } type preferSetter struct { - http.RoundTripper - cfg *cli.Config } -func (s preferSetter) RoundTrip(req *http.Request) (*http.Response, error) { - path := req.URL.Path +func (s preferSetter) RoundTripper(next http.RoundTripper) http.RoundTripper { + return RoundTripFunc(func(req *http.Request) (*http.Response, error) { + path := req.URL.Path - var value []string + var value []string - if s.cfg.Test.Prefer[path].Code != 0 { - value = append(value, fmt.Sprintf("code=%d", s.cfg.Test.Prefer[path].Code)) - } + if s.cfg.Test.Prefer[path].Code != 0 { + value = append(value, fmt.Sprintf("code=%d", s.cfg.Test.Prefer[path].Code)) + } - if s.cfg.Test.Prefer[path].Dynamic { - value = append(value, fmt.Sprintf("dynamic=%t", s.cfg.Test.Prefer[path].Dynamic)) - } + if s.cfg.Test.Prefer[path].Dynamic { + value = append(value, fmt.Sprintf("dynamic=%t", s.cfg.Test.Prefer[path].Dynamic)) + } - if s.cfg.Test.Prefer[path].Example != "" { - value = append(value, fmt.Sprintf("example=%s", s.cfg.Test.Prefer[path].Example)) - } + if s.cfg.Test.Prefer[path].Example != "" { + value = append(value, fmt.Sprintf("example=%s", s.cfg.Test.Prefer[path].Example)) + } - if len(value) > 0 { - req.Header.Set("Prefer", strings.Join(value, " ")) - } + if len(value) > 0 { + req.Header.Set("Prefer", strings.Join(value, " ")) + } - return s.RoundTripper.RoundTrip(req) + return next.RoundTrip(req) + }) } -type userAgentSetter struct { - http.RoundTripper -} +var userAgentSetter = MiddlewareFunc(func(next http.RoundTripper) http.RoundTripper { + return RoundTripFunc(func(req *http.Request) (*http.Response, error) { + req.Header.Set("User-Agent", cli.UserAgent()) -func (s userAgentSetter) RoundTrip(req *http.Request) (*http.Response, error) { - req.Header.Set("User-Agent", cli.UserAgent()) + return next.RoundTrip(req) + }) +}) - return s.RoundTripper.RoundTrip(req) -} +var autoRetrier = MiddlewareFunc(func(next http.RoundTripper) http.RoundTripper { + return RoundTripFunc(func(req *http.Request) (*http.Response, error) { + res, err := next.RoundTrip(req) + if res == nil { + return res, err + } + + switch res.StatusCode { + case http.StatusBadGateway, http.StatusServiceUnavailable: + // TODO: configure a backoff/sleep here? + return next.RoundTrip(req) + default: + return res, err + } + }) +}) type mediaTypes []string @@ -472,3 +513,14 @@ func gnomeKeyringMissing(cfg *cli.Config) bool { } return true } + +type Filter[T any] func(s []T) []T + +type Filters[T any] []Filter[T] + +func (f Filters[T]) Apply(s []T) []T { + for _, fn := range f { + s = fn(s) + } + return s +} diff --git a/api/apitest/apitest.go b/api/apitest/apitest.go index acc871d..3ba0cc7 100644 --- a/api/apitest/apitest.go +++ b/api/apitest/apitest.go @@ -32,9 +32,6 @@ type Server struct { URL string RailsPort string - proxy bool - verbose bool - stopfn func() waitfn func() } @@ -44,10 +41,30 @@ func (s *Server) Close() { s.waitfn() } +func (s *Server) IsMock() bool { + return !proxy +} + func (s *Server) IsProxy() bool { return proxy } +func (s *Server) RecreateUser(username string) error { + if !s.IsProxy() { + return nil + } + + cmd := exec.Command("script/clitest-recreate-user", username) + cmd.Dir = s.RootDir + + _, err := cmd.Output() + if err != nil { + return err + } + + return nil +} + func (s *Server) GeneratePAT(email string) (string, error) { if !s.IsProxy() { return "test-token", nil @@ -97,7 +114,7 @@ func (s *Server) StartMock(ctx context.Context) error { s.URL = "http://" + host + ":" + port + "/v0" s.stopfn = stopfn - s.waitfn = func() { waitfn() } + s.waitfn = func() { _ = waitfn() } return nil } @@ -113,7 +130,7 @@ func (s *Server) StartProxy(ctx context.Context) error { addrRails, waitRails, err := s.startRails(ctx) if err != nil { - lock.Unlock() + _ = lock.Unlock() stopfn() return err } @@ -131,7 +148,7 @@ func (s *Server) StartProxy(ctx context.Context) error { addr, waitPrism, err := s.startProxy(ctx, host+":"+port) if err != nil { - lock.Unlock() + _ = lock.Unlock() stopfn() return err } @@ -142,7 +159,7 @@ func (s *Server) StartProxy(ctx context.Context) error { group.Go(func() error { return s.waitTCP(addrRails) }) if err := group.Wait(); err != nil { - lock.Unlock() + _ = lock.Unlock() stopfn() return err } @@ -165,9 +182,8 @@ func (s *Server) StartProxy(ctx context.Context) error { s.URL = "http://" + host + ":" + port + "/v0" s.stopfn = stopfn s.waitfn = func() { - defer lock.Unlock() - - group.Wait() + _ = group.Wait() + _ = lock.Unlock() } return nil diff --git a/api/openapi.gen.go b/api/openapi.gen.go index 131269a..24078b2 100644 --- a/api/openapi.gen.go +++ b/api/openapi.gen.go @@ -1,6 +1,6 @@ // Package api provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/deepmap/oapi-codegen version v1.16.2 DO NOT EDIT. +// Code generated by github.com/deepmap/oapi-codegen version v1.16.3 DO NOT EDIT. package api import ( diff --git a/api/openapi.go b/api/openapi.go new file mode 100644 index 0000000..2d9146b --- /dev/null +++ b/api/openapi.go @@ -0,0 +1,26 @@ +package api + +import "slices" + +func (o Organization) Key() string { return o.Apid } +func (o Organization) String() string { return o.Name } +func (o Organization) Plural() string { return "organizations" } +func (o Organization) Singular() string { return "organization" } + +func (r Realm) Key() string { return r.Apid } +func (r Realm) String() string { return r.Name } +func (r Realm) Plural() string { return "realms" } +func (r Realm) Singular() string { return "realm" } + +func (s Service) Key() string { return s.Slug } +func (s Service) String() string { return s.Name } +func (s Service) Plural() string { return "services" } +func (s Service) Singular() string { return "service" } + +func NonDiagnosticServices(s []Service) []Service { + return slices.DeleteFunc(s, func(svc Service) bool { + return svc.ServerType == ServiceServerTypeDiagnostic + }) +} + +var _ Filter[Service] = NonDiagnosticServices diff --git a/auth/signin_test.go b/auth/signin_test.go index 3a019e6..4c45b58 100644 --- a/auth/signin_test.go +++ b/auth/signin_test.go @@ -15,16 +15,13 @@ func TestCmdAuthSignin(t *testing.T) { func TestSignIn(t *testing.T) { t.Run("cli-auth-success", func(t *testing.T) { t.Skip("cli auth test not yet implemented") - return }) t.Run("valid-config-token", func(t *testing.T) { t.Skip("cli auth test not yet implemented") - return }) t.Run("invalid-config-token", func(t *testing.T) { t.Skip("cli auth test not yet implemented") - return }) } diff --git a/auth/testdata/TestSignout/signed-out.golden b/auth/testdata/TestSignout/signed-out.golden index 26c9bb9..7a02e80 100644 --- a/auth/testdata/TestSignout/signed-out.golden +++ b/auth/testdata/TestSignout/signed-out.golden @@ -1,6 +1,8 @@ ─── SignOutHeader ────────────────────────────────────────────────────────────── + # Signout from Anchor.dev `anchor auth signout` ─── SignOutSignedOut ─────────────────────────────────────────────────────────── + # Signout from Anchor.dev `anchor auth signout` - Not signed in. | Run `anchor auth signin` to sign in. diff --git a/auth/testdata/TestWhoAmI/signed-in-but-out-of-date-cli-release.golden b/auth/testdata/TestWhoAmI/signed-in-but-out-of-date-cli-release.golden index 58bf949..b849966 100644 --- a/auth/testdata/TestWhoAmI/signed-in-but-out-of-date-cli-release.golden +++ b/auth/testdata/TestWhoAmI/signed-in-but-out-of-date-cli-release.golden @@ -1,9 +1,13 @@ ─── WhoAmIHeader ─────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` ─── WhoAmIChecker ────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` * Identifying Anchor.dev account… ⠋ ─── MinimumVersionCheck ──────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` * Identifying Anchor.dev account… ⠋ -This version of the Anchor CLI is out-of-date, please update. + +# Error! This version of the Anchor CLI is out-of-date, please update. diff --git a/auth/testdata/TestWhoAmI/signed-in.golden b/auth/testdata/TestWhoAmI/signed-in.golden index 4d53f76..1974c23 100644 --- a/auth/testdata/TestWhoAmI/signed-in.golden +++ b/auth/testdata/TestWhoAmI/signed-in.golden @@ -1,8 +1,11 @@ ─── WhoAmIHeader ─────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` ─── WhoAmIChecker ────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` * Identifying Anchor.dev account… ⠋ ─── WhoAmIChecker ────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` - Identified Anchor.dev account: anky@anchor.dev diff --git a/auth/testdata/TestWhoAmI/signed-out.golden b/auth/testdata/TestWhoAmI/signed-out.golden index 5d4dcd4..ed62b38 100644 --- a/auth/testdata/TestWhoAmI/signed-out.golden +++ b/auth/testdata/TestWhoAmI/signed-out.golden @@ -1,9 +1,12 @@ ─── WhoAmIHeader ─────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` ─── WhoAmIChecker ────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` * Identifying Anchor.dev account… ⠋ ─── WhoAmIChecker ────────────────────────────────────────────────────────────── + # Identify Current Anchor.dev Account `anchor auth whoami` - Identified Anchor.dev account: not signed in. | Run `anchor auth signin` to sign in. diff --git a/cert/models/provision.go b/cert/models/provision.go index eddd2ab..4701633 100644 --- a/cert/models/provision.go +++ b/cert/models/provision.go @@ -10,7 +10,10 @@ import ( ) type Provision struct { - Domains []string + Domains []string + OrgAPID string + RealmAPID string + ServiceAPID string certFile, chainFile, keyFile string @@ -56,8 +59,16 @@ func (m *Provision) View() string { fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf("Wrote chain to %s", ui.Emphasize(m.chainFile)))) fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf("Wrote key to %s", ui.Emphasize(m.keyFile)))) - fmt.Fprintln(&b, ui.StepHint("To use these certificates please reference your language and/or framework docs.")) - fmt.Fprintln(&b, ui.StepHint("When these certificates expire, rerun `anchor lcl mkcert` to generate new ones.")) + fmt.Fprintln(&b, ui.Header("Next Steps")) + fmt.Fprintln(&b, ui.StepNext("To use these certificates please reference your language and/or framework docs.")) + fmt.Fprintln(&b, ui.StepNext( + fmt.Sprintf("When these expire, run `anchor lcl mkcert --domains %s --org %s --realm %s --service %s` to generate new ones.", + strings.Join(m.Domains, ","), + m.OrgAPID, + m.RealmAPID, + m.ServiceAPID, + ), + )) return b.String() } diff --git a/cert/provision.go b/cert/provision.go index a586317..f7a26c2 100644 --- a/cert/provision.go +++ b/cert/provision.go @@ -16,13 +16,25 @@ import ( type Provision struct { Cert *tls.Certificate + + Domains []string + OrgAPID string + RealmAPID string + ServiceAPID string +} + +func (p *Provision) RunTUI(ctx context.Context, drv *ui.Driver) error { + return p.Perform(ctx, drv) } -func (p *Provision) RunTUI(ctx context.Context, drv *ui.Driver, domains ...string) error { +func (p *Provision) Perform(ctx context.Context, drv *ui.Driver) error { cfg := cli.ConfigFromContext(ctx) drv.Activate(ctx, &models.Provision{ - Domains: domains, + Domains: p.Domains, + OrgAPID: p.OrgAPID, + RealmAPID: p.RealmAPID, + ServiceAPID: p.ServiceAPID, }) // TODO: as a stand-alone command, it makes no sense to expect a cert as an @@ -32,7 +44,7 @@ func (p *Provision) RunTUI(ctx context.Context, drv *ui.Driver, domains ...strin cert := p.Cert prefix := cert.Leaf.Subject.CommonName - if num := len(domains); num > 1 { + if num := len(p.Domains); num > 1 { prefix += "+" + strconv.Itoa(num-1) } diff --git a/cli.go b/cli.go index 9d091d9..c8ec4b8 100644 --- a/cli.go +++ b/cli.go @@ -128,3 +128,25 @@ func ReportError(ctx context.Context, err error, drv *ui.Driver, cmd *cobra.Comm } } } + +type UserError struct { + Err error +} + +func (u UserError) Error() string { return u.Err.Error() } + +func isReportable(err error) bool { + switch err.(type) { + case UserError: + return false + case ui.Error: + return false + } + + switch err { + case context.Canceled: + return false + } + + return true +} diff --git a/cmd.go b/cmd.go index baaaca5..d2155f6 100644 --- a/cmd.go +++ b/cmd.go @@ -295,16 +295,20 @@ func NewCmd[T UIer](parent *cobra.Command, name string, fn func(*cobra.Command)) err = uierr.Err } - if err != nil && err != context.Canceled { + if err != nil && isReportable(err) { ReportError(ctx, err, drv, cmd, args) } return err } drv.Program.Quit() - if err := <-errc; err != nil && err != context.Canceled { - ReportError(ctx, err, drv, cmd, args) + if err := <-errc; err != nil { + if isReportable(err) { + ReportError(ctx, err, drv, cmd, args) + } + return err } + return nil } diff --git a/component/component_test.go b/component/component_test.go new file mode 100644 index 0000000..9d9fdb2 --- /dev/null +++ b/component/component_test.go @@ -0,0 +1,24 @@ +package component_test + +import ( + "context" + "os" + "testing" + + "github.com/anchordotdev/cli/api/apitest" +) + +var srv = &apitest.Server{ + Host: "api.anchor.lcl.host", + RootDir: "../..", +} + +func TestMain(m *testing.M) { + if err := srv.Start(context.Background()); err != nil { + panic(err) + } + + defer os.Exit(m.Run()) + + srv.Close() +} diff --git a/component/fetcher.go b/component/fetcher.go new file mode 100644 index 0000000..96ae9e5 --- /dev/null +++ b/component/fetcher.go @@ -0,0 +1,32 @@ +package component + +import ( + "context" + + "github.com/anchordotdev/cli/component/models" + "github.com/anchordotdev/cli/ui" +) + +type Choosable = models.Choosable + +type Fetcher[T Choosable] struct { + FetchFn func() ([]T, error) +} + +func (f *Fetcher[T]) Choices(ctx context.Context, drv *ui.Driver, flag string, creatable bool) ([]T, error) { + var t T + drv.Activate(ctx, &models.Fetcher[T]{ + Flag: flag, + Plural: t.Plural(), + Singular: t.Singular(), + Creatable: creatable, + }) + + items, err := f.FetchFn() + if err != nil { + return nil, err + } + + drv.Send(items) + return items, nil +} diff --git a/component/models/selectors.go b/component/models/selectors.go index 0c15183..cf6f13e 100644 --- a/component/models/selectors.go +++ b/component/models/selectors.go @@ -2,38 +2,46 @@ package models import ( "fmt" + "reflect" "strings" - "github.com/anchordotdev/cli/ui" "github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" + + "github.com/anchordotdev/cli/ui" ) -type SelectorChoices[T comparable] interface { - Flag() string - Plural() string - Singular() string +type Choosable interface { + comparable + + Key() string + String() string - ListItems() []ui.ListItem[T] + Singular() string + Plural() string } -type SelectorFetcher[T comparable, U SelectorChoices[T]] struct { - choices U +type Fetcher[T Choosable] struct { + Flag, Plural, Singular string + + Creatable bool + + items []T spinner spinner.Model } -func (m *SelectorFetcher[T, U]) Init() tea.Cmd { +func (m *Fetcher[T]) Init() tea.Cmd { m.spinner = ui.WaitingSpinner() return m.spinner.Tick } -func (m *SelectorFetcher[T, U]) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +func (m *Fetcher[T]) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { - case U: - m.choices = msg + case []T: + m.items = msg } var cmd tea.Cmd @@ -41,44 +49,65 @@ func (m *SelectorFetcher[T, U]) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, cmd } -func (m *SelectorFetcher[T, U]) View() string { - var b strings.Builder - - // TODO: handle case where items is empty after fetch - - items := m.choices.ListItems() - if len(items) == 0 { - fmt.Fprintln(&b, ui.StepInProgress( - fmt.Sprintf("Fetching %s…%s", - m.choices.Plural(), - m.spinner.View()))) - return b.String() +func (m *Fetcher[T]) View() string { + if m.items == nil { + return fmt.Sprintln( + ui.StepInProgress(fmt.Sprintf("Fetching %s…%s", + m.Plural, + m.spinner.View(), + )), + ) } - if len(items) == 1 { - item := items[0] - fmt.Fprintln(&b, ui.StepDone( - fmt.Sprintf("Using %s, the only available %s. %s", - ui.Emphasize(item.Key), - m.choices.Singular(), - ui.Whisper(fmt.Sprintf("You can also use `%s %s`.", m.choices.Flag(), item.Key)), - ))) - } + switch len(m.items) { + case 0: + if m.Creatable { + return fmt.Sprintln( + ui.StepDone(fmt.Sprintf("No %s found, so we'll create one.", + m.Plural, + )), + ) + } - return b.String() + return fmt.Sprintln( + ui.StepAlert(fmt.Sprintf("No %s found!", + m.Plural, + )), + ) + case 1: + item := m.items[0] + + if !m.Creatable { + return fmt.Sprintln( + ui.StepDone(fmt.Sprintf("Using %s, the only available %s. %s", + ui.Emphasize(item.Key()), + m.Singular, + ui.Whisper( + fmt.Sprintf("You can also use `%s %s`.", + m.Flag, + item.Key(), + ), + ), + )), + ) + } + } + return "" } -type Selector[T comparable] struct { +type Selector[T Choosable] struct { + Prompt string + Flag string + Choices []ui.ListItem[T] + ChoiceCh chan<- T - Choices SelectorChoices[T] - Prompt string - choice ui.ListItem[T] + chosen ui.ListItem[T] list list.Model } func (m *Selector[T]) Init() tea.Cmd { - m.list = ui.List(m.Choices.ListItems()) + m.list = ui.List(m.Choices) return nil } @@ -89,9 +118,9 @@ func (m *Selector[T]) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg.Type { case tea.KeyEnter: if item, ok := m.list.SelectedItem().(ui.ListItem[T]); ok { - m.choice = item if m.ChoiceCh != nil { - m.ChoiceCh <- m.choice.Value + m.chosen = item + m.ChoiceCh <- m.chosen.Value close(m.ChoiceCh) m.ChoiceCh = nil } @@ -115,12 +144,20 @@ func (m *Selector[T]) View() string { return b.String() } + if reflect.ValueOf(m.chosen.Value).IsZero() { + fmt.Fprintln(&b, ui.StepDone( + fmt.Sprintf("Selected %s.", ui.Emphasize(m.chosen.String)), + )) + return b.String() + } + fmt.Fprintln(&b, ui.StepDone( fmt.Sprintf("Selected %s %s. %s", - ui.Emphasize(m.choice.Key), - m.Choices.Singular(), - ui.Whisper(fmt.Sprintf("You can also use `%s %s`.", m.Choices.Flag(), m.choice.Key)), - ))) + ui.Emphasize(m.chosen.Key), + m.chosen.Value.Singular(), + ui.Whisper(fmt.Sprintf("You can also use `%s %s`.", m.Flag, m.chosen.Key)), + ), + )) return b.String() } diff --git a/component/selector.go b/component/selector.go new file mode 100644 index 0000000..65f8a52 --- /dev/null +++ b/component/selector.go @@ -0,0 +1,86 @@ +package component + +import ( + "context" + "fmt" + + "golang.org/x/text/cases" + "golang.org/x/text/language" + + "github.com/anchordotdev/cli/component/models" + "github.com/anchordotdev/cli/ui" +) + +type Selector[T Choosable] struct { + Prompt string + Flag string + + Creatable bool + + Choices []T + Fetcher *Fetcher[T] +} + +func (s *Selector[T]) Choice(ctx context.Context, drv *ui.Driver) (*T, error) { + if s.Fetcher != nil { + var err error + if s.Choices, err = s.Fetcher.Choices(ctx, drv, s.Flag, s.Creatable); err != nil { + return nil, err + } + + if len(s.Choices) == 1 && !s.Creatable { + return &s.Choices[0], nil + } + if len(s.Choices) == 0 { + if s.Creatable { + return nil, nil + } + + var t T + return nil, ui.Error{ + Model: ui.Section{ + Name: "FetcherNoneFound", + Model: ui.MessageLines{ + ui.Header(fmt.Sprintf("%s %s", + ui.Danger("Error!"), + fmt.Sprintf("Cannot proceed without %s.", t.Singular()), + )), + }, + }, + } + } + } + + var choices []ui.ListItem[T] + for _, item := range s.Choices { + choice := ui.ListItem[T]{ + Key: item.Key(), + String: fmt.Sprintf("%s (%s)", item.String(), item.Key()), + Value: item, + } + choices = append(choices, choice) + } + if s.Creatable { + var t T + choices = append(choices, ui.ListItem[T]{ + String: fmt.Sprintf("Create New %s", cases.Title(language.English).String(t.Singular())), + }) + } + + choicec := make(chan T) + mdl := &models.Selector[T]{ + Prompt: s.Prompt, + Flag: s.Flag, + + Choices: choices, + ChoiceCh: choicec, + } + drv.Activate(ctx, mdl) + + select { + case choice := <-choicec: + return &choice, nil + case <-ctx.Done(): + return nil, ctx.Err() + } +} diff --git a/component/selectors_test.go b/component/selector_test.go similarity index 55% rename from component/selectors_test.go rename to component/selector_test.go index fd8b7c6..f969018 100644 --- a/component/selectors_test.go +++ b/component/selector_test.go @@ -2,35 +2,20 @@ package component_test import ( "context" + "errors" "fmt" - "os" "testing" "time" "github.com/anchordotdev/cli" "github.com/anchordotdev/cli/api" - "github.com/anchordotdev/cli/api/apitest" "github.com/anchordotdev/cli/component" + "github.com/anchordotdev/cli/ui" "github.com/anchordotdev/cli/ui/uitest" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/x/exp/teatest" ) -var srv = &apitest.Server{ - Host: "api.anchor.lcl.host", - RootDir: "../..", -} - -func TestMain(m *testing.M) { - if err := srv.Start(context.Background()); err != nil { - panic(err) - } - - defer os.Exit(m.Run()) - - srv.Close() -} - func TestSelector(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -63,13 +48,21 @@ func TestSelector(t *testing.T) { errc := make(chan error, 1) go func() { - choicec, err := component.OrgSelector(ctx, drv, anc, "Which organization do you want for this test?") + selector := component.Selector[api.Organization]{ + Prompt: "Which organization do you want for this test?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) if err != nil { errc <- err + return } - org := <-choicec - if want, got := "solo-org-slug", org.Slug; want != got { errc <- fmt.Errorf("Want org choice: %q, Got: %q", want, got) } @@ -102,13 +95,22 @@ func TestSelector(t *testing.T) { choicec := make(chan api.Organization, 1) errc := make(chan error, 1) go func() { - selectorChoicec, err := component.OrgSelector(ctx, drv, anc, "Which organization do you want for this test?") + selector := component.Selector[api.Organization]{ + Prompt: "Which organization do you want for this test?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) if err != nil { errc <- err + return } - choicec <- <-selectorChoicec - + choicec <- *org errc <- tm.Quit() }() @@ -133,4 +135,50 @@ func TestSelector(t *testing.T) { uitest.TestGolden(t, drv.Golden()) }) + t.Run("orgs empty", func(t *testing.T) { + if srv.IsProxy() { + t.Skip("selector tests unsupported in proxy mode") + } + + cfg.Test.Prefer = map[string]cli.ConfigTestPrefer{ + "/v0/orgs": { + Example: "empty", + }, + } + ctx = cli.ContextWithConfig(ctx, cfg) + + drv, tm := uitest.TestTUI(ctx, t) + + errc := make(chan error, 1) + go func() { + selector := component.Selector[api.Organization]{ + Prompt: "Which organization do you want for this test?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) + if org != nil { + errc <- fmt.Errorf("want nil org, got %v", org) + } + var uierr ui.Error + if errors.As(err, &uierr) { + drv.Activate(context.Background(), uierr.Model) + errc <- uierr + } + + errc <- tm.Quit() + }() + + err := <-errc + if err == nil { + t.Fatal("want ui.Error, got nil") + } + + tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) + uitest.TestGolden(t, drv.Golden()) + }) } diff --git a/component/selectors.go b/component/selectors.go deleted file mode 100644 index d6e7238..0000000 --- a/component/selectors.go +++ /dev/null @@ -1,146 +0,0 @@ -package component - -import ( - "context" - "fmt" - - "github.com/anchordotdev/cli/api" - "github.com/anchordotdev/cli/component/models" - "github.com/anchordotdev/cli/ui" -) - -type OrgChoices []api.Organization - -func (OrgChoices) Flag() string { return "--org" } -func (OrgChoices) Plural() string { return "organizations" } -func (OrgChoices) Singular() string { return "organization" } - -func (c OrgChoices) ListItems() []ui.ListItem[api.Organization] { - var items []ui.ListItem[api.Organization] - for _, org := range c { - item := ui.ListItem[api.Organization]{ - Key: org.Apid, - String: fmt.Sprintf("%s (%s)", org.Name, org.Apid), - Value: org, - } - items = append(items, item) - } - return items -} - -func OrgSelector(ctx context.Context, drv *ui.Driver, anc *api.Session, prompt string) (chan api.Organization, error) { - choicec := make(chan api.Organization, 1) - - drv.Activate(ctx, &models.SelectorFetcher[api.Organization, OrgChoices]{}) - orgs, err := anc.GetOrgs(ctx) - if err != nil { - return nil, err - } - choices := OrgChoices(orgs) - drv.Send(choices) - - if len(orgs) == 1 { - choicec <- orgs[0] - return choicec, nil - } - - drv.Activate(ctx, &models.Selector[api.Organization]{ - ChoiceCh: choicec, - Choices: choices, - Prompt: prompt, - }) - - return choicec, nil -} - -type RealmChoices []api.Realm - -func (RealmChoices) Flag() string { return "--realm" } -func (RealmChoices) Plural() string { return "realms" } -func (RealmChoices) Singular() string { return "realm" } - -func (c RealmChoices) ListItems() []ui.ListItem[api.Realm] { - var items []ui.ListItem[api.Realm] - for _, realm := range c { - item := ui.ListItem[api.Realm]{ - Key: realm.Apid, - String: fmt.Sprintf("%s (%s)", realm.Name, realm.Apid), - Value: realm, - } - items = append(items, item) - } - return items -} - -func RealmSelector(ctx context.Context, drv *ui.Driver, anc *api.Session, orgApid string, prompt string) (chan api.Realm, error) { - choicec := make(chan api.Realm, 1) - - drv.Activate(ctx, &models.SelectorFetcher[api.Realm, RealmChoices]{}) - - realms, err := anc.GetOrgRealms(ctx, orgApid) - if err != nil { - return nil, err - } - - choices := RealmChoices(realms) - drv.Send(choices) - - if len(realms) == 1 { - choicec <- realms[0] - return choicec, nil - } - - drv.Activate(ctx, &models.Selector[api.Realm]{ - ChoiceCh: choicec, - Choices: choices, - Prompt: prompt, - }) - - return choicec, nil -} - -type ServiceChoices []api.Service - -func (ServiceChoices) Flag() string { return "--service" } -func (ServiceChoices) Plural() string { return "services" } -func (ServiceChoices) Singular() string { return "service" } - -func (c ServiceChoices) ListItems() []ui.ListItem[api.Service] { - var items []ui.ListItem[api.Service] - for _, service := range c { - item := ui.ListItem[api.Service]{ - Key: service.Slug, - String: fmt.Sprintf("%s (%s)", service.Name, service.Slug), - Value: service, - } - items = append(items, item) - } - return items -} - -func ServiceSelector(ctx context.Context, drv *ui.Driver, anc *api.Session, orgApid string, prompt string) (chan api.Service, error) { - choicec := make(chan api.Service, 1) - - drv.Activate(ctx, &models.SelectorFetcher[api.Service, ServiceChoices]{}) - - services, err := anc.GetOrgServices(ctx, orgApid) - if err != nil { - return nil, err - } - - choices := ServiceChoices(services) - drv.Send(choices) - - if len(services) == 1 { - choicec <- services[0] - return choicec, nil - } - - drv.Activate(ctx, &models.Selector[api.Service]{ - ChoiceCh: choicec, - Choices: choices, - Prompt: prompt, - }) - - return choicec, nil -} diff --git a/component/testdata/TestSelector/orgs_double.golden b/component/testdata/TestSelector/orgs_double.golden index ecee379..72f7671 100644 --- a/component/testdata/TestSelector/orgs_double.golden +++ b/component/testdata/TestSelector/orgs_double.golden @@ -1,4 +1,4 @@ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── * Fetching organizations…⠋ ─── Selector[github.com/anchordotdev/cli/api.Organization] ───────────────────── ? Which organization do you want for this test? diff --git a/component/testdata/TestSelector/orgs_empty.golden b/component/testdata/TestSelector/orgs_empty.golden new file mode 100644 index 0000000..e853317 --- /dev/null +++ b/component/testdata/TestSelector/orgs_empty.golden @@ -0,0 +1,8 @@ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + ! No organizations found! +─── FetcherNoneFound ─────────────────────────────────────────────────────────── + ! No organizations found! + +# Error! Cannot proceed without organization. diff --git a/component/testdata/TestSelector/orgs_solo.golden b/component/testdata/TestSelector/orgs_solo.golden index 97ec949..b7de9ae 100644 --- a/component/testdata/TestSelector/orgs_solo.golden +++ b/component/testdata/TestSelector/orgs_solo.golden @@ -1,4 +1,4 @@ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── * Fetching organizations…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── - Using solo-org-slug, the only available organization. You can also use `--org solo-org-slug`. diff --git a/config.go b/config.go index a2d3b08..a4c2d00 100644 --- a/config.go +++ b/config.go @@ -20,7 +20,9 @@ type Config struct { } Lcl struct { - Service string `desc:"Name for lcl.host diagnostic service." flag:"service" env:"SERVICE" json:"service" toml:"service"` + Org string `desc:"Organization for lcl.host local development environment management." flag:"org,o" env:"ORG" json:"org" toml:"org"` + Realm string `desc:"Realm for lcl.host local development environment management." flag:"realm,r" env:"REALM" json:"realm" toml:"realm"` + Service string `desc:"Service for lcl.host local development environment management." flag:"service" env:"SERVICE" json:"service" toml:"service"` Subdomain string `desc:"Subdomain for lcl.host diagnostic service." flag:"subdomain" env:"SUBDOMAIN" json:"subdomain" toml:"subdomain"` DiagnosticAddr string `default:":4433" desc:"Local server address" flag:"addr,a" env:"ADDR" json:"address" toml:"address"` diff --git a/diagnostic/server.go b/diagnostic/server.go index 1dc03d5..e7884f5 100644 --- a/diagnostic/server.go +++ b/diagnostic/server.go @@ -10,6 +10,7 @@ import ( "sync" "github.com/inetaf/tcpproxy" + "golang.org/x/sync/errgroup" ) var discardLogger = log.New(io.Discard, "", 0) @@ -24,7 +25,8 @@ type Server struct { proxy *tcpproxy.Proxy server *http.Server - ln net.Listener + ln net.Listener + errg errgroup.Group rchanmu sync.Mutex rchan chan string @@ -69,14 +71,17 @@ func (s *Server) Start(ctx context.Context) error { ErrorLog: discardLogger, } - go s.server.Serve(lnHTTP) - go s.server.Serve(tls.NewListener(lnTLS, &tls.Config{ - NextProtos: []string{"h2", "http/1.1"}, - GetCertificate: s.getCertificate, - })) + s.errg.Go(func() error { + return s.server.Serve(lnHTTP) + }) + s.errg.Go(func() error { + return s.server.Serve(tls.NewListener(lnTLS, &tls.Config{ + NextProtos: []string{"h2", "http/1.1"}, + GetCertificate: s.getCertificate, + })) + }) s.tlsc = make(chan struct{}) - return s.proxy.Start() } @@ -97,6 +102,10 @@ func (s *Server) Close() error { return err } + if err := s.errg.Wait(); err != nil { + return err + } + return s.proxy.Wait() } @@ -116,10 +125,11 @@ func (s *Server) RequestChan() <-chan string { } func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) { + var body string if r.TLS != nil { s.notifyRequest("https") - w.Write([]byte(` + body = ` -`)) +` } else { s.notifyRequest("http") - w.Write([]byte(` + body = ` -`)) +` } + + _, _ = w.Write([]byte(body)) } func (s *Server) notifyRequest(scheme string) { diff --git a/go.mod b/go.mod index cc4f097..69710e5 100644 --- a/go.mod +++ b/go.mod @@ -12,22 +12,23 @@ require ( github.com/charmbracelet/lipgloss v0.11.0 github.com/charmbracelet/x/exp/teatest v0.0.0-20240222131549-03ee51df8bea github.com/cli/browser v1.3.0 - github.com/deepmap/oapi-codegen v1.16.2 - github.com/gofrs/flock v0.8.1 + github.com/deepmap/oapi-codegen v1.16.3 + github.com/gofrs/flock v0.11.0 github.com/google/go-github/v54 v54.0.0 github.com/inetaf/tcpproxy v0.0.0-20240214030015-3ce58045626c github.com/joeshaw/envdecode v0.0.0-20200121155833-099f1fc765bd github.com/mcuadros/go-defaults v1.2.0 github.com/muesli/termenv v0.15.2 github.com/oapi-codegen/runtime v1.1.1 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 - github.com/zalando/go-keyring v0.2.4 - golang.org/x/crypto v0.23.0 + github.com/zalando/go-keyring v0.2.5 + golang.org/x/crypto v0.24.0 golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.20.0 + golang.org/x/sys v0.21.0 + golang.org/x/text v0.16.0 howett.net/plist v1.0.1 ) @@ -49,7 +50,6 @@ require ( github.com/go-openapi/swag v0.22.4 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -70,11 +70,10 @@ require ( github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.25.0 // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/text v0.15.0 // indirect - golang.org/x/tools v0.19.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 139f668..5980f72 100644 --- a/go.sum +++ b/go.sum @@ -37,15 +37,15 @@ github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEf github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deepmap/oapi-codegen v1.16.2 h1:xGHx0dNqYfy9gE8a7AVgVM8Sd5oF9SEgePzP+UPAUXI= -github.com/deepmap/oapi-codegen v1.16.2/go.mod h1:rdYoEA2GE+riuZ91DvpmBX9hJbQpuY9wchXpfQ3n+ho= +github.com/deepmap/oapi-codegen v1.16.3 h1:GT9G86SbQtT1r8ZB+4Cybi9VGdu1P5ieNvNdEoCSbrA= +github.com/deepmap/oapi-codegen v1.16.3/go.mod h1:JD6ErqeX0nYnhdciLc61Konj3NBASREMlkHOgHn8WAM= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/getkin/kin-openapi v0.118.0 h1:z43njxPmJ7TaPpMSCQb7PN0dEYno4tyBPQcrFdHoLuM= @@ -60,8 +60,8 @@ github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.11.0 h1:AGFQxrpWd8ezw60AvLWIPbxMydNfF8564pwH3FCty0g= +github.com/gofrs/flock v0.11.0/go.mod h1:FirDy1Ing0mI2+kB6wk+vyyAH+e6xiE+EYA0jnzV9jc= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -139,8 +139,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y= github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -162,24 +162,24 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zalando/go-keyring v0.2.4 h1:wi2xxTqdiwMKbM6TWwi+uJCG/Tum2UV0jqaQhCa9/68= -github.com/zalando/go-keyring v0.2.4/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= +github.com/zalando/go-keyring v0.2.5 h1:Bc2HHpjALryKD62ppdEzaFG6VxL6Bc+5v0LYpN8Lba8= +github.com/zalando/go-keyring v0.2.5/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 h1:6R2FC06FonbXQ8pK11/PDFY6N6LWlf9KlzibaCapmqc= golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -194,21 +194,21 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= -golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= diff --git a/lcl/config_test.go b/lcl/config_test.go index 8d6e3f5..2d9666a 100644 --- a/lcl/config_test.go +++ b/lcl/config_test.go @@ -82,9 +82,13 @@ func TestLclConfig(t *testing.T) { errc := make(chan error, 1) go func() { - errc <- cmd.UI().RunTUI(ctx, drv) + defer close(errc) - tm.Quit() + if err := cmd.UI().RunTUI(ctx, drv); err != nil { + errc <- err + return + } + errc <- tm.Quit() }() // wait for prompt diff --git a/lcl/lcl.go b/lcl/lcl.go index 0e6d624..79ca669 100644 --- a/lcl/lcl.go +++ b/lcl/lcl.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "encoding/base64" + "fmt" "time" "golang.org/x/crypto/acme" @@ -12,6 +13,7 @@ import ( "github.com/anchordotdev/cli" "github.com/anchordotdev/cli/api" "github.com/anchordotdev/cli/auth" + "github.com/anchordotdev/cli/component" "github.com/anchordotdev/cli/lcl/models" "github.com/anchordotdev/cli/ui" "github.com/spf13/cobra" @@ -20,6 +22,10 @@ import ( var CmdLcl = cli.NewCmd[Command](cli.CmdRoot, "lcl", func(cmd *cobra.Command) { cfg := cli.ConfigFromCmd(cmd) + cmd.Flags().StringVarP(&cfg.Lcl.Org, "org", "o", "", "Organization for lcl.host local development environment management.") + cmd.Flags().StringVarP(&cfg.Lcl.Realm, "realm", "r", "", "Realm for lcl.host local development environment management.") + cmd.Flags().StringVarP(&cfg.Lcl.Service, "service", "s", "", "Service for lcl.host local development environment management.") + // config cmd.Flags().StringVarP(&cfg.Lcl.DiagnosticAddr, "addr", "a", ":4433", "Address for local diagnostic web server.") @@ -34,6 +40,8 @@ var CmdLcl = cli.NewCmd[Command](cli.CmdRoot, "lcl", func(cmd *cobra.Command) { type Command struct { anc *api.Session + + OrgAPID, RealmAPID string } func (c Command) UI() cli.UI { @@ -44,6 +52,8 @@ func (c Command) UI() cli.UI { func (c *Command) run(ctx context.Context, drv *ui.Driver) error { var err error + cfg := cli.ConfigFromContext(ctx) + cmd := &auth.Client{ Anc: c.anc, Hint: models.LclSignInHint, @@ -58,22 +68,22 @@ func (c *Command) run(ctx context.Context, drv *ui.Driver) error { drv.Activate(ctx, models.LclHeader) drv.Activate(ctx, models.LclHint) - userInfo, err := c.anc.UserInfo(ctx) + orgAPID, err := c.orgAPID(ctx, cfg, drv) if err != nil { return err } - orgSlug := userInfo.PersonalOrg.Slug - realmSlug := "localhost" + realmAPID, err := c.realmAPID(ctx, cfg, drv, orgAPID) + if err != nil { + return err + } // run audit command drv.Activate(ctx, models.AuditHeader) drv.Activate(ctx, models.AuditHint) cmdAudit := &Audit{ - anc: c.anc, - orgSlug: orgSlug, - realmSlug: realmSlug, + anc: c.anc, } lclAuditResult, err := cmdAudit.perform(ctx, drv) @@ -89,9 +99,7 @@ func (c *Command) run(ctx context.Context, drv *ui.Driver) error { drv.Activate(ctx, models.LclConfigHint) cmdConfig := &LclConfig{ - anc: c.anc, - orgSlug: orgSlug, - realmSlug: realmSlug, + anc: c.anc, } if err := cmdConfig.perform(ctx, drv); err != nil { @@ -104,8 +112,10 @@ func (c *Command) run(ctx context.Context, drv *ui.Driver) error { drv.Activate(ctx, models.SetupHint) cmdSetup := &Setup{ - anc: c.anc, - orgSlug: orgSlug, + OrgAPID: orgAPID, + RealmAPID: realmAPID, + ServiceAPID: cfg.Lcl.Service, // TODO: cfg access here looks wrong + anc: c.anc, } err = cmdSetup.perform(ctx, drv) @@ -116,6 +126,54 @@ func (c *Command) run(ctx context.Context, drv *ui.Driver) error { return nil } +func (c *Command) orgAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (string, error) { + if c.OrgAPID != "" { + return c.OrgAPID, nil + } + if cfg.Lcl.Org != "" { + return cfg.Lcl.Org, nil + } + + selector := &component.Selector[api.Organization]{ + Prompt: "Which organization do you want to manage your local development environment for?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return c.anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return org.Apid, nil +} + +func (c *Command) realmAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID string) (string, error) { + if c.RealmAPID != "" { + return c.RealmAPID, nil + } + if cfg.Lcl.Realm != "" { + return cfg.Lcl.Realm, nil + } + + selector := &component.Selector[api.Realm]{ + Prompt: fmt.Sprintf("Which %s realm do you want to manage your local development environment for?", ui.Emphasize(orgAPID)), + Flag: "--realm", + + Fetcher: &component.Fetcher[api.Realm]{ + FetchFn: func() ([]api.Realm, error) { return c.anc.GetOrgRealms(ctx, orgAPID) }, + }, + } + + realm, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return realm.Apid, nil +} + func provisionCert(eab *api.Eab, domains []string, acmeURL string) (*tls.Certificate, error) { hmacKey, err := base64.URLEncoding.DecodeString(eab.HmacKey) if err != nil { diff --git a/lcl/lcl_test.go b/lcl/lcl_test.go index 3673466..8b01801 100644 --- a/lcl/lcl_test.go +++ b/lcl/lcl_test.go @@ -108,11 +108,16 @@ func TestLcl(t *testing.T) { httpURL := "http://hello-world.lcl.host:" + diagPort httpsURL := "https://hello-world.lcl.host:" + diagPort + // ensure lcl has no leftover data + err = srv.RecreateUser("lcl_setup") + if err != nil { + t.Fatal(err) + } + cfg := new(cli.Config) cfg.API.URL = srv.URL - cfg.AnchorURL = "http://anchor.lcl.host:" + srv.RailsPort + "/" + cfg.AnchorURL = "http://anchor.lcl.host:" + srv.RailsPort cfg.Lcl.DiagnosticAddr = diagAddr - cfg.Lcl.Service = "hi-ankydotdev" cfg.Lcl.Subdomain = "hi-ankydotdev" cfg.Trust.MockMode = true cfg.Trust.NoSudo = true @@ -199,43 +204,29 @@ func TestLcl(t *testing.T) { t.Fatal(err) } + // setup + uitest.WaitForGoldenContains(t, drv, errc, "? What application server type?", ) - tm.Send(tea.KeyMsg{ - Type: tea.KeyEnter, - }) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) uitest.WaitForGoldenContains(t, drv, errc, "? What is the application name?", ) tm.Type("test-app") - tm.Send(tea.KeyMsg{ - Type: tea.KeyEnter, - }) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) uitest.WaitForGoldenContains(t, drv, errc, "? What lcl.host domain would you like to use for local application development?", ) - if !srv.IsProxy() { - t.Skip("provisioning unsupported in mock mode") - } - - tm.Send(tea.KeyMsg{ - Type: tea.KeyEnter, - }) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) uitest.WaitForGoldenContains(t, drv, errc, - "? What certificate management method?", - ) - uitest.WaitForGoldenContains(t, drv, errc, - "Automatic via ACME - Anchor style - Recommended", - ) - uitest.WaitForGoldenContains(t, drv, errc, - "Manually Managed - mkcert style", + "? How would you like to manage your lcl.host certificates?", ) tm.Send(tea.KeyMsg{ diff --git a/lcl/mkcert.go b/lcl/mkcert.go index e1f81ad..e1dd650 100644 --- a/lcl/mkcert.go +++ b/lcl/mkcert.go @@ -4,12 +4,14 @@ import ( "context" "crypto/tls" "errors" + "fmt" "net/url" "github.com/anchordotdev/cli" "github.com/anchordotdev/cli/api" "github.com/anchordotdev/cli/auth" "github.com/anchordotdev/cli/cert" + "github.com/anchordotdev/cli/component" "github.com/anchordotdev/cli/ui" "github.com/spf13/cobra" ) @@ -17,21 +19,26 @@ import ( var CmdLclMkCert = cli.NewCmd[MkCert](CmdLcl, "mkcert", func(cmd *cobra.Command) { cfg := cli.ConfigFromCmd(cmd) + cmd.Flags().StringVarP(&cfg.Lcl.Org, "org", "o", "", "Organization to create certificate for.") + cmd.Flags().StringVarP(&cfg.Lcl.Realm, "realm", "r", "", "Realm to create certificate for.") + cmd.Flags().StringVarP(&cfg.Lcl.Service, "service", "s", "", "Service to create certificate for.") + cmd.Flags().StringSliceVar(&cfg.Lcl.MkCert.Domains, "domains", []string{}, "Domains to create certificate for.") - cmd.Flags().StringVar(&cfg.Lcl.MkCert.SubCa, "subca", "", "SubCA to create certificate for.") }) type MkCert struct { anc *api.Session - domains []string - eab *api.Eab + domains []string + eab *api.Eab + OrgAPID string + RealmAPID string + ServiceAPID string + + // optional - chainSlug string - orgSlug string - realmSlug string - serviceSlug string - subCaSubjectUID string + ChainAPID string + SubCaAPID string } func (c MkCert) UI() cli.UI { @@ -56,65 +63,58 @@ func (c *MkCert) run(ctx context.Context, drv *ui.Driver) error { return err } - cmdCert := cert.Provision{ - Cert: tlsCert, - } - - if err := cmdCert.RunTUI(ctx, drv, c.domains...); err != nil { - return err + cmdCertProvision := cert.Provision{ + Cert: tlsCert, + Domains: c.domains, + OrgAPID: c.OrgAPID, + RealmAPID: c.RealmAPID, + ServiceAPID: c.ServiceAPID, } - return nil + return cmdCertProvision.Perform(ctx, drv) } func (c *MkCert) perform(ctx context.Context, drv *ui.Driver) (*tls.Certificate, error) { cfg := cli.ConfigFromContext(ctx) - var err error - - if c.chainSlug == "" { - c.chainSlug = "ca" + chainAPID := c.ChainAPID + if chainAPID == "" { + chainAPID = "ca" } if len(c.domains) == 0 { c.domains = cfg.Lcl.MkCert.Domains if len(c.domains) == 0 { - return nil, errors.New("domains is required") + return nil, cli.UserError{Err: errors.New("domains is required")} } } - if c.orgSlug == "" { - userInfo, err := c.anc.UserInfo(ctx) - if err != nil { - return nil, err - } - c.orgSlug = userInfo.PersonalOrg.Slug + orgAPID, err := c.orgAPID(ctx, cfg, drv) + if err != nil { + return nil, err } - if c.realmSlug == "" { - c.realmSlug = "localhost" + realmAPID, err := c.realmAPID(ctx, cfg, drv, orgAPID) + if err != nil { + return nil, err } - if c.serviceSlug == "" { - c.serviceSlug = cfg.Lcl.Service - if c.serviceSlug == "" { - return nil, errors.New("service is required") - } + serviceAPID, err := c.serviceAPID(ctx, cfg, drv, orgAPID, realmAPID) + if err != nil { + return nil, err } - if c.subCaSubjectUID == "" { - c.subCaSubjectUID = cfg.Lcl.MkCert.SubCa - if c.subCaSubjectUID == "" { - return nil, errors.New("subca is required") - } + subCaAPID, err := c.subcaAPID(ctx, cfg, orgAPID, realmAPID, chainAPID, serviceAPID) + if err != nil { + return nil, err } - c.eab, err = c.anc.CreateEAB(ctx, c.chainSlug, c.orgSlug, c.realmSlug, c.serviceSlug, c.subCaSubjectUID) + c.eab, err = c.anc.CreateEAB(ctx, chainAPID, orgAPID, realmAPID, serviceAPID, subCaAPID) if err != nil { return nil, err } - acmeURL := cfg.AnchorURL + "/" + url.QueryEscape(c.orgSlug) + "/" + url.QueryEscape(c.realmSlug) + "/x509/" + c.chainSlug + "/acme" + acmeURL := cfg.AnchorURL + "/" + url.QueryEscape(orgAPID) + "/" + url.QueryEscape(realmAPID) + "/x509/" + chainAPID + "/acme" tlsCert, err := provisionCert(c.eab, c.domains, acmeURL) if err != nil { @@ -123,3 +123,102 @@ func (c *MkCert) perform(ctx context.Context, drv *ui.Driver) (*tls.Certificate, return tlsCert, nil } + +func (c *MkCert) orgAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (string, error) { + if c.OrgAPID != "" { + return c.OrgAPID, nil + } + if cfg.Lcl.Org != "" { + return cfg.Lcl.Org, nil + } + + selector := &component.Selector[api.Organization]{ + Prompt: "Which organization's certificates do you want to create?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return c.anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return org.Apid, nil +} + +func (c *MkCert) realmAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID string) (string, error) { + if c.RealmAPID != "" { + return c.RealmAPID, nil + } + if cfg.Lcl.Realm != "" { + return cfg.Lcl.Realm, nil + } + + selector := &component.Selector[api.Realm]{ + Prompt: fmt.Sprintf("Which %s realm's certificates do you want to create?", ui.Emphasize(orgAPID)), + Flag: "--realm", + + Fetcher: &component.Fetcher[api.Realm]{ + FetchFn: func() ([]api.Realm, error) { return c.anc.GetOrgRealms(ctx, orgAPID) }, + }, + } + + realm, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return realm.Apid, nil +} + +func (c *MkCert) serviceAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID, realmAPID string) (string, error) { + if c.ServiceAPID != "" { + return c.ServiceAPID, nil + } + if cfg.Lcl.Service != "" { + return cfg.Lcl.Service, nil + } + + selector := &component.Selector[api.Service]{ + Prompt: fmt.Sprintf("Which %s/%s service's certificates do you want to create?", ui.Emphasize(orgAPID), ui.Emphasize(realmAPID)), + Flag: "--service", + + Fetcher: &component.Fetcher[api.Service]{ + FetchFn: func() ([]api.Service, error) { return c.anc.GetOrgServices(ctx, orgAPID, api.NonDiagnosticServices) }, + }, + } + + service, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + if service == nil { + return "", nil + } + return service.Slug, nil +} + +func (c *MkCert) subcaAPID(ctx context.Context, cfg *cli.Config, orgAPID, realmAPID, chainAPID, serviceAPID string) (string, error) { + if c.SubCaAPID != "" { + return c.SubCaAPID, nil + } + if cfg.Lcl.MkCert.SubCa != "" { + return cfg.Lcl.MkCert.SubCa, nil + } + + attachments, err := c.anc.GetServiceAttachments(ctx, orgAPID, serviceAPID) + if err != nil { + return "", err + } + + for _, a := range attachments { + if a.Relationships.Realm.Apid == realmAPID && a.Relationships.Chain.Apid == chainAPID { + return *a.Relationships.SubCa.Apid, nil + } + } + + return "", cli.UserError{ + Err: fmt.Errorf("invalid org, realm, and service combination"), + } +} diff --git a/lcl/mkcert_test.go b/lcl/mkcert_test.go index 7ebdb75..7d88322 100644 --- a/lcl/mkcert_test.go +++ b/lcl/mkcert_test.go @@ -20,9 +20,19 @@ func TestCmdLclMkCert(t *testing.T) { require.Equal(t, []string{"test.lcl.host", "test.localhost"}, cfg.Lcl.MkCert.Domains) }) - t.Run("--subca 1234:ABCD:EF123", func(t *testing.T) { - cfg := cmdtest.TestCfg(t, CmdLclMkCert, "--subca", "1234:ABCD:EF123") - require.Equal(t, "1234:ABCD:EF123", cfg.Lcl.MkCert.SubCa) + t.Run("--org test-org", func(t *testing.T) { + cfg := cmdtest.TestCfg(t, CmdLclMkCert, "--org", "test-org") + require.Equal(t, "test-org", cfg.Lcl.Org) + }) + + t.Run("--service test-service", func(t *testing.T) { + cfg := cmdtest.TestCfg(t, CmdLclMkCert, "--service", "test-service") + require.Equal(t, "test-service", cfg.Lcl.Service) + }) + + t.Run("--realm test-realm", func(t *testing.T) { + cfg := cmdtest.TestCfg(t, CmdLclMkCert, "--realm", "test-realm") + require.Equal(t, "test-realm", cfg.Lcl.Realm) }) } @@ -54,8 +64,7 @@ func TestLclMkcert(t *testing.T) { defer cancel() cmd := MkCert{ - domains: []string{"hi-lcl-mkcert.lcl.host", "hi-lcl-mkcert.localhost"}, - subCaSubjectUID: "ABCD:EF12:23456", + domains: []string{"hi-lcl-mkcert.lcl.host", "hi-lcl-mkcert.localhost"}, } uitest.TestTUIOutput(ctx, t, cmd.UI()) diff --git a/lcl/models/audit.go b/lcl/models/audit.go index a6a9be3..fce79f3 100644 --- a/lcl/models/audit.go +++ b/lcl/models/audit.go @@ -22,7 +22,7 @@ var ( AuditHint = ui.Section{ Name: "AuditHint", Model: ui.MessageLines{ - ui.StepHint("We'll begin by checking your system to determine what you need for your setup."), + ui.StepHint("We'll determine what needs setup on your system."), }, } ) diff --git a/lcl/models/clean.go b/lcl/models/clean.go index 6292f1b..b4af4a5 100644 --- a/lcl/models/clean.go +++ b/lcl/models/clean.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/anchordotdev/cli/ui" - "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" ) @@ -18,27 +17,17 @@ var LclCleanHeader = ui.Section{ type LclCleanHint struct { TrustStores []string - - spinner spinner.Model } -func (c *LclCleanHint) Init() tea.Cmd { - c.spinner = ui.WaitingSpinner() - - return c.spinner.Tick -} +func (c *LclCleanHint) Init() tea.Cmd { return nil } -func (c *LclCleanHint) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmd tea.Cmd - c.spinner, cmd = c.spinner.Update(msg) - return c, cmd -} +func (c *LclCleanHint) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return c, nil } func (c *LclCleanHint) View() string { stores := strings.Join(c.TrustStores, ", ") var b strings.Builder - fmt.Fprintln(&b, ui.Hint(fmt.Sprintf("Removing lcl.host CA certificates from the %s store(s).", stores))) + fmt.Fprintln(&b, ui.Hint(fmt.Sprintf("We'll remove lcl.host CA certificates from the %s store(s).", stores))) return b.String() } diff --git a/lcl/models/config.go b/lcl/models/config.go index 58dd113..1257cc4 100644 --- a/lcl/models/config.go +++ b/lcl/models/config.go @@ -13,7 +13,7 @@ var ( LclConfigSkip = ui.Section{ Name: "LclConfigSkip", Model: ui.MessageLines{ - ui.Skip("Configure System for lcl.host Local Development `anchor lcl config`"), + ui.Skip("Configure System for lcl.host HTTPS Local Development `anchor lcl config`"), }, } diff --git a/lcl/models/lcl.go b/lcl/models/lcl.go index f3ae1e6..6e2741e 100644 --- a/lcl/models/lcl.go +++ b/lcl/models/lcl.go @@ -40,7 +40,7 @@ var ( LclHint = ui.Section{ Name: "LclHint", Model: ui.MessageLines{ - ui.StepHint("After setup, you can use HTTPS locally in your browsers and other programs."), + ui.StepHint("We'll set you up to use HTTPS locally in your browsers and other programs."), }, } ) @@ -199,7 +199,7 @@ func (m *DomainInput) View() string { if m.InputCh != nil { fmt.Fprintln(&b, ui.StepPrompt(m.Prompt)) - fmt.Fprintln(&b, ui.StepHint("We will ignore any characters that are not valid in a domain.")) + fmt.Fprintln(&b, ui.StepHint("We'll ignore any characters that are not valid in a domain.")) fmt.Fprintln(&b, ui.StepPrompt(m.input.View())) } else { fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf(m.Done, ui.Emphasize(m.Domain)))) diff --git a/lcl/models/setup.go b/lcl/models/setup.go index f33a9ff..effa764 100644 --- a/lcl/models/setup.go +++ b/lcl/models/setup.go @@ -24,7 +24,7 @@ var ( SetupHint = ui.Section{ Name: "SetupHint", Model: ui.MessageLines{ - ui.StepHint("We'll gather details from you and your system to customize setup instructions."), + ui.StepHint("We'll integrate your application and system for HTTPS local development."), }, } ) @@ -233,12 +233,12 @@ type SetupMethod struct { func (m *SetupMethod) Init() tea.Cmd { m.list = ui.List([]ui.ListItem[string]{ { - Key: "automatic", - String: "Automatic via ACME - Anchor style - Recommended", + Key: "automated", + String: "ACME Automated - Anchor style guides you through setup and automates renewal - Recommended", }, { Key: "manual", - String: "Manually Managed - mkcert style", + String: "Manual - mkcert style leaves setup and renewal up to you", }, }) return nil @@ -272,11 +272,7 @@ func (m *SetupMethod) View() string { var b strings.Builder if m.ChoiceCh != nil { - fmt.Fprintln(&b, ui.StepHint("How would you like to manage your lcl.host certificates?")) - fmt.Fprintln(&b, ui.StepHint(" - Anchor style guides you through setup and will automatically renew.")) - fmt.Fprintln(&b, ui.StepHint(" - Mkcert style leaves setup and renewal up to you.")) - - fmt.Fprintln(&b, ui.StepPrompt("What certificate management method?")) + fmt.Fprintln(&b, ui.StepPrompt("How would you like to manage your lcl.host certificates?")) fmt.Fprintln(&b, m.list.View()) return b.String() } diff --git a/lcl/provision.go b/lcl/provision.go index 59b23f1..909480d 100644 --- a/lcl/provision.go +++ b/lcl/provision.go @@ -45,19 +45,21 @@ func (p *Provision) run(ctx context.Context, drv *ui.Driver, anc *api.Session, s // FIXME: we need to lookup and pass the chain and/or make it non-optional chainParam := "ca" - attach, err := anc.AttachService(ctx, chainParam, p.Domains, p.orgSlug, p.realmSlug, serviceParam) + attach, err := anc.AttachService(ctx, chainParam, p.Domains, p.orgSlug, p.realmSlug, srv.Slug) if err != nil { return nil, nil, err } + subCaSubjectUID := attach.Relationships.SubCa.Slug cmdMkCert := &MkCert{ - anc: anc, - chainSlug: attach.Relationships.Chain.Slug, - domains: p.Domains, - orgSlug: p.orgSlug, - realmSlug: p.realmSlug, - serviceSlug: serviceParam, - subCaSubjectUID: attach.Relationships.SubCa.Slug, + anc: anc, + domains: p.Domains, + OrgAPID: p.orgSlug, + RealmAPID: p.realmSlug, + ServiceAPID: srv.Slug, + + ChainAPID: attach.Relationships.Chain.Slug, + SubCaAPID: subCaSubjectUID, } tlsCert, err := cmdMkCert.perform(ctx, drv) diff --git a/lcl/setup.go b/lcl/setup.go index 7fc9b0f..09bd17e 100644 --- a/lcl/setup.go +++ b/lcl/setup.go @@ -20,9 +20,14 @@ import ( "github.com/anchordotdev/cli/api" "github.com/anchordotdev/cli/auth" "github.com/anchordotdev/cli/cert" + "github.com/anchordotdev/cli/component" "github.com/anchordotdev/cli/detection" "github.com/anchordotdev/cli/lcl/models" climodels "github.com/anchordotdev/cli/models" + "github.com/anchordotdev/cli/service" + servicemodels "github.com/anchordotdev/cli/service/models" + "github.com/anchordotdev/cli/trust" + trustmodels "github.com/anchordotdev/cli/trust/models" "github.com/anchordotdev/cli/ui" ) @@ -31,16 +36,22 @@ var CmdLclSetup = cli.NewCmd[Setup](CmdLcl, "setup", func(cmd *cobra.Command) { cmd.Flags().StringVar(&cfg.Lcl.Setup.Language, "language", "", "Language to integrate with Anchor.") cmd.Flags().StringVar(&cfg.Lcl.Setup.Method, "method", "", "Integration method for certificates.") + cmd.Flags().StringVarP(&cfg.Lcl.Org, "org", "o", "", "Organization for lcl.host application setup.") + cmd.Flags().StringVarP(&cfg.Lcl.Realm, "realm", "r", "", "Realm for lcl.host application setup.") + cmd.Flags().StringVarP(&cfg.Lcl.Service, "service", "s", "", "Service for lcl.host application setup.") }) var ( - MethodAutomatic = "automatic" + MethodAnchor = "anchor" + MethodAutomated = "automated" MethodManual = "manual" + MethodMkcert = "mkcert" ) type Setup struct { - anc *api.Session - orgSlug string + OrgAPID, RealmAPID, ServiceAPID string + + anc *api.Session } func (c Setup) UI() cli.UI { @@ -74,16 +85,109 @@ func (c *Setup) run(ctx context.Context, drv *ui.Driver) error { func (c *Setup) perform(ctx context.Context, drv *ui.Driver) error { cfg := cli.ConfigFromContext(ctx) - drv.Activate(ctx, &models.SetupScan{}) + orgAPID, err := c.orgAPID(ctx, cfg, drv) + if err != nil { + return err + } - if c.orgSlug == "" { - userInfo, err := c.anc.UserInfo(ctx) - if err != nil { - return err - } - c.orgSlug = userInfo.PersonalOrg.Slug + realmAPID, err := c.realmAPID(ctx, cfg, drv, orgAPID) + if err != nil { + return err + } + + serviceAPID, err := c.serviceAPID(ctx, cfg, drv, orgAPID, realmAPID) + if err != nil { + return err + } + if serviceAPID == "" { + return c.createNewService(ctx, drv, orgAPID, realmAPID) + } + + return c.setupService(ctx, drv, orgAPID, realmAPID, serviceAPID) +} + +func (c *Setup) orgAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (string, error) { + if c.OrgAPID != "" { + return c.OrgAPID, nil + } + if cfg.Lcl.Org != "" { + return cfg.Lcl.Org, nil } + selector := &component.Selector[api.Organization]{ + Prompt: "Which organization's lcl.host local development environment do you want to setup?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return c.anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return org.Apid, nil +} + +func (c *Setup) realmAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID string) (string, error) { + if c.RealmAPID != "" { + return c.RealmAPID, nil + } + if cfg.Lcl.Realm != "" { + return cfg.Lcl.Realm, nil + } + + selector := &component.Selector[api.Realm]{ + Prompt: fmt.Sprintf("Which %s realm's lcl.host local development environment do you want to setup?", ui.Emphasize(orgAPID)), + Flag: "--realm", + + Fetcher: &component.Fetcher[api.Realm]{ + FetchFn: func() ([]api.Realm, error) { return c.anc.GetOrgRealms(ctx, orgAPID) }, + }, + } + + realm, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return realm.Apid, nil +} + +func (c *Setup) serviceAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID, realmAPID string) (string, error) { + if c.ServiceAPID != "" { + return c.ServiceAPID, nil + } + if cfg.Service.Env.Service != "" { + return cfg.Service.Env.Service, nil + } + + selector := &component.Selector[api.Service]{ + Prompt: fmt.Sprintf("Which %s/%s service's lcl.host local development environment do you want to setup?", ui.Emphasize(orgAPID), ui.Emphasize(realmAPID)), + Flag: "--service", + + Creatable: true, + + Fetcher: &component.Fetcher[api.Service]{ + FetchFn: func() ([]api.Service, error) { return c.anc.GetOrgServices(ctx, orgAPID, api.NonDiagnosticServices) }, + }, + } + + service, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + if service == nil { + return "", nil + } + return service.Slug, nil +} + +func (c *Setup) createNewService(ctx context.Context, drv *ui.Driver, orgAPID, realmAPID string) error { + cfg := cli.ConfigFromContext(ctx) + + drv.Activate(ctx, &models.SetupScan{}) + path, err := os.Getwd() if err != nil { return err @@ -170,12 +274,11 @@ func (c *Setup) perform(ctx context.Context, drv *ui.Driver) error { subdomain := strings.TrimSuffix(lclDomain, ".lcl.host") domains := []string{lclDomain, subdomain + ".localhost"} - realmSlug := "localhost" cmdProvision := &Provision{ Domains: domains, - orgSlug: c.orgSlug, - realmSlug: realmSlug, + orgSlug: orgAPID, + realmSlug: realmAPID, } service, tlsCert, err := cmdProvision.run(ctx, drv, c.anc, serviceName, serviceCategory, nil) @@ -198,36 +301,62 @@ func (c *Setup) perform(ctx context.Context, drv *ui.Driver) error { } switch setupMethod { - case MethodManual: - if err := c.manualMethod(ctx, drv, tlsCert, domains...); err != nil { - return err - } - case MethodAutomatic: - setupGuideURL := cfg.AnchorURL + "/" + url.QueryEscape(c.orgSlug) + "/services/" + url.QueryEscape(service.Slug) + "/guide" + case MethodManual, MethodMkcert: + return c.manualMethod(ctx, drv, orgAPID, realmAPID, service.Slug, tlsCert, domains...) + case MethodAnchor, MethodAutomated: + setupGuideURL := cfg.AnchorURL + "/" + url.QueryEscape(orgAPID) + "/services/" + url.QueryEscape(service.Slug) + "/guide" lclURL := fmt.Sprintf("https://%s:%d", lclDomain, *service.LocalhostPort) - if err := c.automaticMethod(ctx, drv, setupGuideURL, lclURL); err != nil { - return err - } + return c.automatedMethod(ctx, drv, setupGuideURL, lclURL) default: return fmt.Errorf("Unknown method: %s. Please choose either `anchor` (recommended) or `mkcert`.", setupMethod) } - - return nil } -func (c *Setup) manualMethod(ctx context.Context, drv *ui.Driver, tlsCert *tls.Certificate, domains ...string) error { - cmdCert := cert.Provision{ - Cert: tlsCert, +func (c *Setup) setupService(ctx context.Context, drv *ui.Driver, orgAPID, realmAPID, serviceAPID string) error { + drv.Activate(ctx, trustmodels.TrustHeader) + drv.Activate(ctx, trustmodels.TrustHint) + + cmdTrust := &trust.Command{ + Anc: c.anc, + OrgSlug: orgAPID, + RealmSlug: realmAPID, } - if err := cmdCert.RunTUI(ctx, drv, domains...); err != nil { + if err := cmdTrust.Perform(ctx, drv); err != nil { + return err + } + + drv.Activate(ctx, servicemodels.ServiceEnvHeader) + drv.Activate(ctx, servicemodels.ServiceEnvHint) + + cmdServiceEnv := &service.Env{ + Anc: c.anc, + OrgAPID: orgAPID, + RealmAPID: realmAPID, + ServiceAPID: serviceAPID, + } + + err := cmdServiceEnv.Perform(ctx, drv) + if err != nil { return err } return nil } -func (c *Setup) automaticMethod(ctx context.Context, drv *ui.Driver, setupGuideURL string, LclURL string) error { +func (c *Setup) manualMethod(ctx context.Context, drv *ui.Driver, orgAPID string, realmAPID string, serviceAPID string, tlsCert *tls.Certificate, domains ...string) error { + cmdCertProvision := cert.Provision{ + Cert: tlsCert, + Domains: domains, + OrgAPID: orgAPID, + RealmAPID: realmAPID, + ServiceAPID: serviceAPID, + } + + return cmdCertProvision.Perform(ctx, drv) +} + +func (c *Setup) automatedMethod(ctx context.Context, drv *ui.Driver, setupGuideURL string, LclURL string) error { setupGuideConfirmCh := make(chan struct{}) drv.Activate(ctx, &models.SetupGuidePrompt{ @@ -263,10 +392,10 @@ var ( // based on: https://apidock.com/rails/ActiveSupport/Inflector/parameterize func parameterize(value string) string { + value = strings.ToLower(value) // fwiw: not part of rails parameterize value = parameterizeUnwantedRegex.ReplaceAllString(value, "-") value = parameterizeDuplicateSeparatorRegex.ReplaceAllString(value, "-") value = parameterizeLeadingTrailingRegex.ReplaceAllString(value, "") - value = strings.ToLower(value) // fwiw: not part of rails parameterize return value } diff --git a/lcl/setup_test.go b/lcl/setup_test.go index 1a7cd04..4f77e18 100644 --- a/lcl/setup_test.go +++ b/lcl/setup_test.go @@ -34,15 +34,18 @@ func TestSetup(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() + // ensure lcl_setup has no leftover data + err := srv.RecreateUser("lcl_setup") + if err != nil { + t.Fatal(err) + } + cfg := new(cli.Config) cfg.API.URL = srv.URL - cfg.AnchorURL = "http://anchor.lcl.host:" + srv.RailsPort + "/" - cfg.Lcl.Service = "hi-ankydotdev" - cfg.Lcl.Subdomain = "hi-ankydotdev" + cfg.AnchorURL = "http://anchor.lcl.host:" + srv.RailsPort cfg.Trust.MockMode = true cfg.Trust.NoSudo = true cfg.Trust.Stores = []string{"mock"} - var err error if cfg.API.Token, err = srv.GeneratePAT("lcl_setup@anchor.dev"); err != nil { t.Fatal(err) } @@ -50,7 +53,11 @@ func TestSetup(t *testing.T) { setupGuideURL := cfg.AnchorURL + "lcl_setup/services/test-app/guide" - t.Run("basics", func(t *testing.T) { + t.Run("create-service-automated-basics", func(t *testing.T) { + if srv.IsMock() { + t.Skip("lcl setup create service unsupported in mock mode") + } + ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -61,49 +68,41 @@ func TestSetup(t *testing.T) { errc := make(chan error, 1) go func() { errc <- cmd.UI().RunTUI(ctx, drv) - - tm.Quit() + errc <- tm.Quit() }() - // wait for prompt - uitest.WaitForGoldenContains(t, drv, errc, "? What application server type?", ) - tm.Send(tea.KeyMsg{ - Type: tea.KeyEnter, - }) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) uitest.WaitForGoldenContains(t, drv, errc, "? What is the application name?", ) tm.Type("test-app") - tm.Send(tea.KeyMsg{ - Type: tea.KeyEnter, - }) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) uitest.WaitForGoldenContains(t, drv, errc, "? What lcl.host domain would you like to use for local application development?", ) - if !srv.IsProxy() { - t.Skip("provisioning unsupported in mock mode") - } - - tm.Send(tea.KeyMsg{ - Type: tea.KeyEnter, - }) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) uitest.WaitForGoldenContains(t, drv, errc, - "? What certificate management method?", + "? How would you like to manage your lcl.host certificates?", ) + // FIXME: partial golden test unless/until setup guide port fixed + uitest.TestGolden(t, drv.Golden()) + t.Skip("Pending workaround for consistent setup guide port value") + tm.Send(tea.KeyMsg{ Type: tea.KeyEnter, }) + uitest.TestGolden(t, drv.Golden()) t.Skip("Pending workaround for consistent setup guide port value") uitest.WaitForGoldenContains(t, drv, errc, @@ -117,4 +116,213 @@ func TestSetup(t *testing.T) { tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) uitest.TestGolden(t, drv.Golden()) }) + + t.Run("create-service-manual-basics", func(t *testing.T) { + if srv.IsMock() { + t.Skip("lcl setup create service unsupported in mock mode") + } + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + drv, tm := uitest.TestTUI(ctx, t) + + cmd := Setup{} + + errc := make(chan error, 1) + go func() { + errc <- cmd.UI().RunTUI(ctx, drv) + errc <- tm.Quit() + }() + + uitest.WaitForGoldenContains(t, drv, errc, + "? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What application server type?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What is the application name?", + ) + + tm.Type("test-app") + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What lcl.host domain would you like to use for local application development?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? How would you like to manage your lcl.host certificates?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) + uitest.TestGolden(t, drv.Golden()) + }) + + t.Run(fmt.Sprintf("existing-service-basics-%s", uitest.TestTagOS()), func(t *testing.T) { + if srv.IsProxy() { + t.Skip("lcl setup existing service unsupported in proxy mode") + } + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + drv, tm := uitest.TestTUI(ctx, t) + + cmd := Setup{} + + errc := make(chan error, 1) + go func() { + errc <- cmd.UI().RunTUI(ctx, drv) + errc <- tm.Quit() + }() + + uitest.WaitForGoldenContains(t, drv, errc, + "? Which org-slug/realm-slug service's lcl.host local development environment do you want to setup?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "! Press Enter to install missing certificates. (requires sudo)", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? How would you like to manage your environment variables?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) + + // FIXME: check clipboard values for accuracy (can't easily access values) + + uitest.TestGolden(t, drv.Golden()) + }) + + t.Run("create-service-with-parameterized-name", func(t *testing.T) { + if srv.IsMock() { + t.Skip("lcl setup create service unsupported in mock mode") + } + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + drv, tm := uitest.TestTUI(ctx, t) + + cmd := Setup{} + + errc := make(chan error, 1) + go func() { + errc <- cmd.UI().RunTUI(ctx, drv) + errc <- tm.Quit() + }() + + uitest.WaitForGoldenContains(t, drv, errc, + "? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What application server type?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What is the application name?", + ) + + tm.Type("Test App") + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What lcl.host domain would you like to use for local application development?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? How would you like to manage your lcl.host certificates?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) + uitest.TestGolden(t, drv.Golden()) + }) + + t.Run("create-service-with-custom-domain", func(t *testing.T) { + if srv.IsMock() { + t.Skip("lcl setup create service unsupported in mock mode") + } + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + drv, tm := uitest.TestTUI(ctx, t) + + cmd := Setup{} + + errc := make(chan error, 1) + go func() { + errc <- cmd.UI().RunTUI(ctx, drv) + errc <- tm.Quit() + }() + + uitest.WaitForGoldenContains(t, drv, errc, + "? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What application server type?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What is the application name?", + ) + + tm.Type("test-explicit-subdomain-app") + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? What lcl.host domain would you like to use for local application development?", + ) + + tm.Type("this-is-my-weird-subdomain") + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + uitest.WaitForGoldenContains(t, drv, errc, + "? How would you like to manage your lcl.host certificates?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) + uitest.TestGolden(t, drv.Golden()) + }) } diff --git a/lcl/testdata/TestAudit/basics.golden b/lcl/testdata/TestAudit/basics.golden index fa3499f..68c4946 100644 --- a/lcl/testdata/TestAudit/basics.golden +++ b/lcl/testdata/TestAudit/basics.golden @@ -3,25 +3,31 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── AuditHeader ──────────────────────────────────────────────────────────────── + # Audit lcl.host HTTPS Local Development Environment `anchor lcl audit` ─── AuditHint ────────────────────────────────────────────────────────────────── + # Audit lcl.host HTTPS Local Development Environment `anchor lcl audit` - | We'll begin by checking your system to determine what you need for your setup. + | We'll determine what needs setup on your system. ─── AuditResources ───────────────────────────────────────────────────────────── + # Audit lcl.host HTTPS Local Development Environment `anchor lcl audit` - | We'll begin by checking your system to determine what you need for your setup. + | We'll determine what needs setup on your system. * Checking resources on Anchor.dev…⠋ ─── AuditResources ───────────────────────────────────────────────────────────── + # Audit lcl.host HTTPS Local Development Environment `anchor lcl audit` - | We'll begin by checking your system to determine what you need for your setup. + | We'll determine what needs setup on your system. - Checked resources on Anchor.dev: need to provision resources. ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Audit lcl.host HTTPS Local Development Environment `anchor lcl audit` - | We'll begin by checking your system to determine what you need for your setup. + | We'll determine what needs setup on your system. - Checked resources on Anchor.dev: need to provision resources. * Comparing local and expected CA certificates…⠋ ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Audit lcl.host HTTPS Local Development Environment `anchor lcl audit` - | We'll begin by checking your system to determine what you need for your setup. + | We'll determine what needs setup on your system. - Checked resources on Anchor.dev: need to provision resources. - Compared local and expected CA certificates: need to install 2 missing certificates. diff --git a/lcl/testdata/TestClean/basics.golden b/lcl/testdata/TestClean/basics.golden index e610809..61152d6 100644 --- a/lcl/testdata/TestClean/basics.golden +++ b/lcl/testdata/TestClean/basics.golden @@ -3,15 +3,19 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── LclCleanHeader ───────────────────────────────────────────────────────────── + # Clean lcl.host CA Certificates from Local Trust Store(s) `anchor trust clean` ─── LclCleanHint ─────────────────────────────────────────────────────────────── + # Clean lcl.host CA Certificates from Local Trust Store(s) `anchor trust clean` -| Removing lcl.host CA certificates from the mock store(s). +| We'll remove lcl.host CA certificates from the mock store(s). ─── TrustCleanAudit ──────────────────────────────────────────────────────────── + # Clean lcl.host CA Certificates from Local Trust Store(s) `anchor trust clean` -| Removing lcl.host CA certificates from the mock store(s). +| We'll remove lcl.host CA certificates from the mock store(s). * Auditing local CA certificates…⠋ ─── TrustCleanAudit ──────────────────────────────────────────────────────────── + # Clean lcl.host CA Certificates from Local Trust Store(s) `anchor trust clean` -| Removing lcl.host CA certificates from the mock store(s). +| We'll remove lcl.host CA certificates from the mock store(s). - Audited local CA certificates: need to remove 0 certificates. diff --git a/lcl/testdata/TestCmdLcl/--help.golden b/lcl/testdata/TestCmdLcl/--help.golden index 69ba415..ffa6af4 100644 --- a/lcl/testdata/TestCmdLcl/--help.golden +++ b/lcl/testdata/TestCmdLcl/--help.golden @@ -17,6 +17,9 @@ Flags: -h, --help help for lcl --language string Language to integrate with Anchor. --method string Integration method for certificates. + -o, --org string Organization for lcl.host local development environment management. + -r, --realm string Realm for lcl.host local development environment management. + -s, --service string Service for lcl.host local development environment management. --subca string SubCA to create certificate for. Use "anchor lcl [command] --help" for more information about a command. diff --git a/lcl/testdata/TestCmdLclMkCert/--help.golden b/lcl/testdata/TestCmdLclMkCert/--help.golden index a895139..1aed1ad 100644 --- a/lcl/testdata/TestCmdLclMkCert/--help.golden +++ b/lcl/testdata/TestCmdLclMkCert/--help.golden @@ -6,4 +6,6 @@ Usage: Flags: --domains strings Domains to create certificate for. -h, --help help for mkcert - --subca string SubCA to create certificate for. + -o, --org string Organization to create certificate for. + -r, --realm string Realm to create certificate for. + -s, --service string Service to create certificate for. diff --git a/lcl/testdata/TestCmdLclSetup/--help.golden b/lcl/testdata/TestCmdLclSetup/--help.golden index 7da74a1..cc7d4f5 100644 --- a/lcl/testdata/TestCmdLclSetup/--help.golden +++ b/lcl/testdata/TestCmdLclSetup/--help.golden @@ -7,3 +7,6 @@ Flags: -h, --help help for setup --language string Language to integrate with Anchor. --method string Integration method for certificates. + -o, --org string Organization for lcl.host application setup. + -r, --realm string Realm for lcl.host application setup. + -s, --service string Service for lcl.host application setup. diff --git a/lcl/testdata/TestLclConfig/basics.golden b/lcl/testdata/TestLclConfig/basics.golden index af10a9d..29b61c5 100644 --- a/lcl/testdata/TestLclConfig/basics.golden +++ b/lcl/testdata/TestLclConfig/basics.golden @@ -3,122 +3,137 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── LclConfigHeader ──────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` ─── LclConfigHint ────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hi-lcl_config.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? h.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? he.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hel.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hell.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hello.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hello-.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hello-w.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hello-wo.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hello-wor.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hello-worl.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. | | We'll start a local diagnostic web server to guide you through the process. ? What lcl.host domain would you like to use for diagnostics? - | We will ignore any characters that are not valid in a domain. + | We'll ignore any characters that are not valid in a domain. ? hello-world.lcl.host ─── DomainInput ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -126,6 +141,7 @@ | We'll start a local diagnostic web server to guide you through the process. - Entered hello-world.lcl.host domain for lcl.host diagnostic certificate. ─── DomainResolver ───────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -134,6 +150,7 @@ - Entered hello-world.lcl.host domain for lcl.host diagnostic certificate. * Resolving hello-world.lcl.host domain…⠋ ─── DomainResolver ───────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -142,6 +159,7 @@ - Entered hello-world.lcl.host domain for lcl.host diagnostic certificate. - Resolved hello-world.lcl.host domain: success! ─── ProvisionService ─────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -152,6 +170,7 @@ | Now we'll provision Anchor.dev resources and HTTPS certificates for you. - Creating hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev… ⠋ ─── ProvisionService ─────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -162,6 +181,7 @@ | Now we'll provision Anchor.dev resources and HTTPS certificates for you. - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. ─── LclConfig ────────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -173,6 +193,7 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. ! Press Enter to open http://hello-world.lcl.host:4433 in your browser. ─── LclConfig ────────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -185,6 +206,7 @@ - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. ─── TrustHeader ──────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -196,8 +218,10 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -209,9 +233,11 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` * Comparing local and expected CA certificates…⠋ ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -223,9 +249,11 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -237,11 +265,13 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. | Updates may require sudo privileges, learn why here: https://lcl.host/why-sudo ! Press Enter to install missing certificates. (requires sudo) ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -253,9 +283,11 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -267,10 +299,12 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. * Updating Mock: installing lcl_config/localhost - AnchorCA ECDSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -282,10 +316,12 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed lcl_config/localhost - AnchorCA [ECDSA] ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -297,11 +333,13 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed lcl_config/localhost - AnchorCA [ECDSA] * Updating Mock: installing lcl_config/localhost - AnchorCA RSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -313,10 +351,12 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed lcl_config/localhost - AnchorCA [ECDSA, RSA] ─── LclConfig ────────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -328,12 +368,14 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed lcl_config/localhost - AnchorCA [ECDSA, RSA] | Before we move on, let's test HTTPS. ! Press Enter to open https://hello-world.lcl.host:4433 in your browser. ─── LclConfig ────────────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -345,11 +387,13 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed lcl_config/localhost - AnchorCA [ECDSA, RSA] | Before we move on, let's test HTTPS. ─── LclConfigSuccess ─────────────────────────────────────────────────────────── + # Configure System for lcl.host HTTPS Local Development `anchor lcl config` | Before issuing HTTPS certificates, we need to configure your browsers | and OS to trust your personal certificates. @@ -361,6 +405,7 @@ - Created hello-world [hello-world.lcl.host, hello-world.localhost] diagnostic resources on Anchor.dev. - Great, http://hello-world.lcl.host:4433 works as expected (without HTTPS). | Next, we'll add your personal CA certificates to your system's trust stores. + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed lcl_config/localhost - AnchorCA [ECDSA, RSA] diff --git a/lcl/testdata/TestSetup/automated-basics.golden b/lcl/testdata/TestSetup/automated-basics.golden new file mode 100644 index 0000000..813104c --- /dev/null +++ b/lcl/testdata/TestSetup/automated-basics.golden @@ -0,0 +1,166 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. +─── SetupScan ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + * Scanning current directory for local application…⠋ +─── SetupScan ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. +─── SetupCategory ────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + ? What application server type? + > Go + JavaScript + Python + Ruby + Custom +─── SetupCategory ────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? lcl +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? t +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? te +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? tes +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test- +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-a +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-ap +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-app +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. +─── DomainInput ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + ? What lcl.host domain would you like to use for local application development? + | We will ignore any characters that are not valid in a domain. + ? test-app.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. +─── DomainResolver ───────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + * Resolving test-app.lcl.host domain…⠋ +─── DomainResolver ───────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! +─── ProvisionService ─────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Creating test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev… ⠋ +─── ProvisionService ─────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. +─── SetupMethod ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + > ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + Manual - mkcert style leaves setup and renewal up to you diff --git a/lcl/testdata/TestSetup/create-service-automated-basics.golden b/lcl/testdata/TestSetup/create-service-automated-basics.golden new file mode 100644 index 0000000..fea6053 --- /dev/null +++ b/lcl/testdata/TestSetup/create-service-automated-basics.golden @@ -0,0 +1,288 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + * Fetching realms…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + * Fetching services…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + * Scanning current directory for local application…⠋ +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + ? What application server type? + > Go + JavaScript + Python + Ruby + Custom +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? lcl +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? t +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? te +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? tes +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test- +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-a +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-ap +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-app +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? test-app.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + * Resolving test-app.lcl.host domain…⠋ +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Creating test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev… ⠋ +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - No services found, so we'll create one. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + > ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + Manual - mkcert style leaves setup and renewal up to you diff --git a/lcl/testdata/TestSetup/create-service-manual-basics.golden b/lcl/testdata/TestSetup/create-service-manual-basics.golden new file mode 100644 index 0000000..aaea986 --- /dev/null +++ b/lcl/testdata/TestSetup/create-service-manual-basics.golden @@ -0,0 +1,387 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + * Fetching realms…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + * Fetching services…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + ? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup? + > test-app (test-app) + Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + ? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup? + test-app (test-app) + > Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + * Scanning current directory for local application…⠋ +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + ? What application server type? + > Go + JavaScript + Python + Ruby + Custom +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? lcl +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? t +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? te +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? tes +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test- +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-a +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-ap +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-app +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? test-app.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + * Resolving test-app.lcl.host domain…⠋ +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Creating test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev… ⠋ +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + > ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + > Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. +─── Provision ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. + +# Provision Certificate `anchor lcl mkcert` + * Provisioning certificate for [test-app.lcl.host, test-app.localhost]… ⠋ +─── Provision ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. + +# Provision Certificate `anchor lcl mkcert` + - Provisioned certificate for [test-app.lcl.host, test-app.localhost]. + - Wrote certificate to ./test-app.lcl.host+1-cert.pem + - Wrote chain to ./test-app.lcl.host+1-chain.pem + - Wrote key to ./test-app.lcl.host+1-key.pem + +# Next Steps + - To use these certificates please reference your language and/or framework docs. + - When these expire, run `anchor lcl mkcert --domains test-app.lcl.host,test-app.localhost --org lcl_setup --realm localhost --service test-app` to generate new ones. diff --git a/lcl/testdata/TestSetup/create-service-with-custom-domain.golden b/lcl/testdata/TestSetup/create-service-with-custom-domain.golden new file mode 100644 index 0000000..5f286a8 --- /dev/null +++ b/lcl/testdata/TestSetup/create-service-with-custom-domain.golden @@ -0,0 +1,934 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + * Fetching realms…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + * Fetching services…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + ? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup? + > test-app (test-app) + Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + ? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup? + test-app (test-app) + > Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + * Scanning current directory for local application…⠋ +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + ? What application server type? + > Go + JavaScript + Python + Ruby + Custom +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? lcl +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? t +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? te +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? tes +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test- +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-e +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-ex +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-exp +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-expl +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-expli +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explic +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explici +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit- +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-s +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-su +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-sub +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subd +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdo +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdom +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdoma +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdomai +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdomain +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdomain- +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdomain-a +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdomain-ap +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-explicit-subdomain-app +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? test-explicit-subdomain-app.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? t.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? th.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? thi.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-i.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-m.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-w.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-we.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-wei.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weir.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-s.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-su.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-sub.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-subd.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-subdo.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-subdom.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-subdoma.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-subdomai.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? this-is-my-weird-subdomain.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + * Resolving this-is-my-weird-subdomain.lcl.host domain…⠋ +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Creating test-explicit-subdomain-app [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost] go resources on Anchor.dev… ⠋ +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-explicit-subdomain-app [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost] go resources on Anchor.dev. +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-explicit-subdomain-app [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + > ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-explicit-subdomain-app [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + > Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-explicit-subdomain-app [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost] go resources on Anchor.dev. + - Entered manual certificate management. +─── Provision ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-explicit-subdomain-app [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost] go resources on Anchor.dev. + - Entered manual certificate management. + +# Provision Certificate `anchor lcl mkcert` + * Provisioning certificate for [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost]… ⠋ +─── Provision ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered test-explicit-subdomain-app application name. + - Entered this-is-my-weird-subdomain.lcl.host domain for local application development. + - Resolved this-is-my-weird-subdomain.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-explicit-subdomain-app [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost] go resources on Anchor.dev. + - Entered manual certificate management. + +# Provision Certificate `anchor lcl mkcert` + - Provisioned certificate for [this-is-my-weird-subdomain.lcl.host, this-is-my-weird-subdomain.localhost]. + - Wrote certificate to ./this-is-my-weird-subdomain.lcl.host+1-cert.pem + - Wrote chain to ./this-is-my-weird-subdomain.lcl.host+1-chain.pem + - Wrote key to ./this-is-my-weird-subdomain.lcl.host+1-key.pem + +# Next Steps + - To use these certificates please reference your language and/or framework docs. + - When these expire, run `anchor lcl mkcert --domains this-is-my-weird-subdomain.lcl.host,this-is-my-weird-subdomain.localhost --org lcl_setup --realm localhost --service test-explicit-subdomain-app` to generate new ones. diff --git a/lcl/testdata/TestSetup/create-service-with-parameterized-name.golden b/lcl/testdata/TestSetup/create-service-with-parameterized-name.golden new file mode 100644 index 0000000..2c5125a --- /dev/null +++ b/lcl/testdata/TestSetup/create-service-with-parameterized-name.golden @@ -0,0 +1,387 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + * Fetching realms…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + * Fetching services…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + ? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup? + > test-app (test-app) + Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + ? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup? + test-app (test-app) + > Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + * Scanning current directory for local application…⠋ +─── SetupScan ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + ? What application server type? + > Go + JavaScript + Python + Ruby + Custom +─── SetupCategory ────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? lcl +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? T +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? Te +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? Tes +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? Test +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? Test +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? Test A +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? Test Ap +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? Test App +─── SetupName ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + ? What lcl.host domain would you like to use for local application development? + | We'll ignore any characters that are not valid in a domain. + ? test-app.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + * Resolving test-app.lcl.host domain…⠋ +─── DomainResolver ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Creating Test App [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev… ⠋ +─── ProvisionService ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created Test App [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created Test App [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + > ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created Test App [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + > Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created Test App [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. +─── Provision ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created Test App [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. + +# Provision Certificate `anchor lcl mkcert` + * Provisioning certificate for [test-app.lcl.host, test-app.localhost]… ⠋ +─── Provision ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using lcl_setup, the only available organization. You can also use `--org lcl_setup`. + - Using localhost, the only available realm. You can also use `--realm localhost`. + - Selected Create New Service. + - Scanned current directory. + - Entered go application server type. + - Entered Test App application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created Test App [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. + +# Provision Certificate `anchor lcl mkcert` + - Provisioned certificate for [test-app.lcl.host, test-app.localhost]. + - Wrote certificate to ./test-app.lcl.host+1-cert.pem + - Wrote chain to ./test-app.lcl.host+1-chain.pem + - Wrote key to ./test-app.lcl.host+1-key.pem + +# Next Steps + - To use these certificates please reference your language and/or framework docs. + - When these expire, run `anchor lcl mkcert --domains test-app.lcl.host,test-app.localhost --org lcl_setup --realm localhost --service test-app` to generate new ones. diff --git a/lcl/testdata/TestSetup/existing-service-basics-unix.golden b/lcl/testdata/TestSetup/existing-service-basics-unix.golden new file mode 100644 index 0000000..8b50f31 --- /dev/null +++ b/lcl/testdata/TestSetup/existing-service-basics-unix.golden @@ -0,0 +1,312 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + * Fetching realms…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + * Fetching services…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + ? Which org-slug/realm-slug service's lcl.host local development environment do you want to setup? + > service-name (service-name) + Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. +─── TrustHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` +─── TrustHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. +─── TrustStoreAudit ──────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + * Comparing local and expected CA certificates…⠋ +─── TrustStoreAudit ──────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. +─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + | Updates may require sudo privileges, learn why here: https://lcl.host/why-sudo + ! Press Enter to install missing certificates. (requires sudo) +─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + * Updating Mock: installing oas-examples - AnchorCA ECDSA… ⠋ +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA] +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA] + * Updating Mock: installing oas-examples - AnchorCA RSA… ⠋ +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] +─── ServiceEnvHeader ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` +─── ServiceEnvHint ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. +─── EnvFetch ─────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + * Fetching service-name environment variables…⠋ +─── EnvFetch ─────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + ? How would you like to manage your environment variables? + > Add export commands to your clipboard. + Add dotenv contents to your clipboard. + Display export commands. ! WARNING: could be observed by others. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Selected export environment variable method. You can also use `--method export`. +─── EnvClipboard ─────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Selected export environment variable method. You can also use `--method export`. + - Copied service-name export commands to your clipboard. + ! Paste and press enter to load your environment variables. +─── EnvNextSteps ─────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Selected export environment variable method. You can also use `--method export`. + - Copied service-name export commands to your clipboard. + ! Paste and press enter to load your environment variables. + +# Next Steps + ! (Re)Start your server. + ! Check out your encrypted site: https://service.lcl.host:4433 + | These certificates will renew automatically, time to enjoy effortless encryption. diff --git a/lcl/testdata/TestSetup/existing-service-basics-windows.golden b/lcl/testdata/TestSetup/existing-service-basics-windows.golden new file mode 100644 index 0000000..9c1050e --- /dev/null +++ b/lcl/testdata/TestSetup/existing-service-basics-windows.golden @@ -0,0 +1,314 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + * Fetching realms…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + * Fetching services…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + ? Which org-slug/realm-slug service's lcl.host local development environment do you want to setup? + > service-name (service-name) + Create New Service +─── Selector[github.com/anchordotdev/cli/api.Service] ────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. +─── TrustHeader ──────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` +─── TrustHint ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. +─── TrustStoreAudit ──────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + * Comparing local and expected CA certificates…⠋ +─── TrustStoreAudit ──────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. +─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + | Updates may require sudo privileges, learn why here: https://lcl.host/why-sudo + ! Press Enter to install missing certificates. (requires sudo) +─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + | "oas-examples - AnchorCA" Thumbprint (sha1): BA470EAC 5067C499 99F3F5A1 ACE9E8CA 48E2731C + * Updating Mock: installing oas-examples - AnchorCA ECDSA… ⠋ +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA] +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA] + | "oas-examples - AnchorCA" Thumbprint (sha1): E1CE91B0 FC124890 24F7583B 8F0844EE 2291BE47 + * Updating Mock: installing oas-examples - AnchorCA RSA… ⠋ +─── TrustUpdateStore ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] +─── ServiceEnvHeader ─────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` +─── ServiceEnvHint ───────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. +─── EnvFetch ─────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + * Fetching service-name environment variables…⠋ +─── EnvFetch ─────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + ? How would you like to manage your environment variables? + > Add export commands to your clipboard. + Add dotenv contents to your clipboard. + Display export commands. ! WARNING: could be observed by others. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Selected export environment variable method. You can also use `--method export`. +─── EnvClipboard ─────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Selected export environment variable method. You can also use `--method export`. + - Copied service-name export commands to your clipboard. + ! Paste and press enter to load your environment variables. +─── EnvNextSteps ─────────────────────────────────────────────────────────────── + +# Setup lcl.host Application `anchor lcl setup` + | We'll integrate your application and system for HTTPS local development. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Selected service-name service. You can also use `--service service-name`. + +# Manage CA Certificates in your Local Trust Store(s) `anchor trust` + | We'll check your local trust stores and make any needed updates. + - Compared local and expected CA certificates: need to install 2 missing certificates. + - Updated Mock: installed oas-examples - AnchorCA [ECDSA, RSA] + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Selected export environment variable method. You can also use `--method export`. + - Copied service-name export commands to your clipboard. + ! Paste and press enter to load your environment variables. + +# Next Steps + ! (Re)Start your server. + ! Check out your encrypted site: https://service.lcl.host:4433 + | These certificates will renew automatically, time to enjoy effortless encryption. diff --git a/lcl/testdata/TestSetup/manual-basics.golden b/lcl/testdata/TestSetup/manual-basics.golden new file mode 100644 index 0000000..67f3459 --- /dev/null +++ b/lcl/testdata/TestSetup/manual-basics.golden @@ -0,0 +1,222 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── SetupHeader ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` +─── SetupHint ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. +─── SetupScan ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + * Scanning current directory for local application…⠋ +─── SetupScan ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. +─── SetupCategory ────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + ? What application server type? + > Go + JavaScript + Python + Ruby + Custom +─── SetupCategory ────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? lcl +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? t +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? te +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? tes +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test- +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-a +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-ap +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + ? What is the application name? + ? test-app +─── SetupName ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. +─── DomainInput ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + ? What lcl.host domain would you like to use for local application development? + | We will ignore any characters that are not valid in a domain. + ? test-app.lcl.host +─── DomainInput ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. +─── DomainResolver ───────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + * Resolving test-app.lcl.host domain…⠋ +─── DomainResolver ───────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! +─── ProvisionService ─────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Creating test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev… ⠋ +─── ProvisionService ─────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. +─── SetupMethod ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + > ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + ? How would you like to manage your lcl.host certificates? + ACME Automated - Anchor style guides you through setup and automates renewal - Recommended + > Manual - mkcert style leaves setup and renewal up to you +─── SetupMethod ──────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. +─── Provision ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. +# Provision Certificate `anchor lcl mkcert` + * Provisioning certificate for [test-app.lcl.host, test-app.localhost]… ⠋ +─── Provision ────────────────────────────────────────────────────────────────── +# Setup lcl.host Application `anchor lcl setup` + | We'll gather details from you and your system to customize setup instructions. + - Scanned current directory. + - Entered go application server type. + - Entered test-app application name. + - Entered test-app.lcl.host domain for local application development. + - Resolved test-app.lcl.host domain: success! + | Now we'll provision Anchor.dev resources and HTTPS certificates for you. + - Created test-app [test-app.lcl.host, test-app.localhost] go resources on Anchor.dev. + - Entered manual certificate management. +# Provision Certificate `anchor lcl mkcert` + - Provisioned certificate for [test-app.lcl.host, test-app.localhost]. + - Wrote certificate to ./test-app.lcl.host+1-cert.pem + - Wrote chain to ./test-app.lcl.host+1-chain.pem + - Wrote key to ./test-app.lcl.host+1-key.pem +# Next Steps + - To use these certificates please reference your language and/or framework docs. + - When these certificates expire, run `anchor lcl mkcert` to generate new ones. diff --git a/service/env.go b/service/env.go index 5bf7bed..a5b79d3 100644 --- a/service/env.go +++ b/service/env.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "net/url" - "os" "sort" "strings" @@ -27,12 +26,11 @@ var ( cmd.Flags().StringVarP(&cfg.Service.Env.Org, "org", "o", "", "Organization to trust.") cmd.Flags().StringVarP(&cfg.Service.Env.Realm, "realm", "r", "", "Realm to trust.") cmd.Flags().StringVarP(&cfg.Service.Env.Service, "service", "s", "", "Service for ENV.") - - cmd.Hidden = true }) - MethodClipboard = "clipboard" - MethodDotenv = "dotenv" + MethodExport = "export" + MethodDotenv = "dotenv" + MethodDisplay = "display" ) type Env struct { @@ -73,62 +71,20 @@ func (c *Env) run(ctx context.Context, drv *ui.Driver) error { func (c *Env) Perform(ctx context.Context, drv *ui.Driver) error { cfg := cli.ConfigFromContext(ctx) - if c.ChainAPID == "" { - c.ChainAPID = "ca" - } - - if c.OrgAPID == "" { - c.OrgAPID = cfg.Service.Env.Org - } - if c.OrgAPID == "" { - choicec, err := component.OrgSelector(ctx, drv, c.Anc, - "Which organization's env do you want to fetch?", - ) - if err != nil { - return err - } - select { - case org := <-choicec: - c.OrgAPID = org.Slug - case <-ctx.Done(): - return ctx.Err() - } + chainAPID := c.chainAPID() + orgAPID, err := c.orgAPID(ctx, cfg, drv) + if err != nil { + return err } - if c.RealmAPID == "" { - c.RealmAPID = cfg.Service.Env.Realm - } - if c.RealmAPID == "" { - choicec, err := component.RealmSelector(ctx, drv, c.Anc, c.OrgAPID, - fmt.Sprintf("Which %s realm's env do you want to fetch?", ui.Emphasize(c.OrgAPID)), - ) - if err != nil { - return err - } - select { - case realm := <-choicec: - c.RealmAPID = realm.Apid - case <-ctx.Done(): - return ctx.Err() - } + realmAPID, err := c.realmAPID(ctx, cfg, drv, orgAPID) + if err != nil { + return err } - if c.ServiceAPID == "" { - c.ServiceAPID = cfg.Service.Env.Service - } - if c.ServiceAPID == "" { - choicec, err := component.ServiceSelector(ctx, drv, c.Anc, c.OrgAPID, - fmt.Sprintf("Which %s/%s service do you want to fetch?", ui.Emphasize(c.OrgAPID), ui.Emphasize(c.RealmAPID)), - ) - if err != nil { - return err - } - select { - case service := <-choicec: - c.ServiceAPID = service.Slug - case <-ctx.Done(): - return ctx.Err() - } + serviceAPID, err := c.serviceAPID(ctx, cfg, drv, orgAPID, realmAPID) + if err != nil { + return err } if c.whoami == "" { @@ -140,28 +96,28 @@ func (c *Env) Perform(ctx context.Context, drv *ui.Driver) error { } drv.Activate(ctx, &models.EnvFetch{ - Service: c.ServiceAPID, + Service: serviceAPID, }) env := make(map[string]string) env["ACME_CONTACT"] = c.whoami - env["ACME_DIRECTORY_URL"] = cfg.AnchorURL + "/" + url.QueryEscape(c.OrgAPID) + "/" + url.QueryEscape(c.RealmAPID) + "/x509/" + c.ChainAPID + "/acme" + env["ACME_DIRECTORY_URL"] = cfg.AnchorURL + "/" + url.QueryEscape(orgAPID) + "/" + url.QueryEscape(realmAPID) + "/x509/" + chainAPID + "/acme" - attachments, err := c.Anc.GetServiceAttachments(ctx, c.OrgAPID, c.ServiceAPID) + attachments, err := c.Anc.GetServiceAttachments(ctx, orgAPID, serviceAPID) if err != nil { return err } var attachment *api.Attachment for _, a := range attachments { - if a.Relationships.Chain.Apid == c.ChainAPID && a.Relationships.Realm.Apid == c.RealmAPID && a.Relationships.SubCa.Apid != nil { + if a.Relationships.Chain.Apid == chainAPID && a.Relationships.Realm.Apid == realmAPID && a.Relationships.SubCa.Apid != nil { attachment = &a break } } if attachment != nil { - eab, err := c.Anc.CreateEAB(ctx, c.ChainAPID, c.OrgAPID, c.RealmAPID, c.ServiceAPID, *attachment.Relationships.SubCa.Apid) + eab, err := c.Anc.CreateEAB(ctx, chainAPID, orgAPID, realmAPID, serviceAPID, *attachment.Relationships.SubCa.Apid) if err != nil { return err } @@ -169,7 +125,7 @@ func (c *Env) Perform(ctx context.Context, drv *ui.Driver) error { env["ACME_HMAC_KEY"] = eab.HmacKey } - service, err := c.Anc.GetService(ctx, c.OrgAPID, c.ServiceAPID) + service, err := c.Anc.GetService(ctx, orgAPID, serviceAPID) if err != nil { return err } @@ -196,18 +152,23 @@ func (c *Env) Perform(ctx context.Context, drv *ui.Driver) error { } switch envMethod { - case MethodClipboard: - err := c.clipboardMethod(ctx, drv, env) + case MethodExport: + err := c.exportMethod(ctx, drv, env, serviceAPID) if err != nil { return err } case MethodDotenv: - err := c.dotenvMethod(ctx, drv, env) + err := c.dotenvMethod(ctx, drv, env, serviceAPID) + if err != nil { + return err + } + case MethodDisplay: + err := c.displayMethod(ctx, drv, env, serviceAPID) if err != nil { return err } default: - return fmt.Errorf("Unknown method: %s. Please choose either `clipboard` or `dotenv`.", envMethod) + return fmt.Errorf("Unknown method: %s. Please choose either `export` or `dotenv`.", envMethod) } var lclDomain string @@ -226,7 +187,7 @@ func (c *Env) Perform(ctx context.Context, drv *ui.Driver) error { return nil } -func (c *Env) clipboardMethod(ctx context.Context, drv *ui.Driver, env map[string]string) error { +func (c *Env) exportMethod(ctx context.Context, drv *ui.Driver, env map[string]string, serviceAPID string) error { var b strings.Builder var keys []string @@ -241,13 +202,13 @@ func (c *Env) clipboardMethod(ctx context.Context, drv *ui.Driver, env map[strin drv.Activate(ctx, &models.EnvClipboard{ InClipboard: (clipboardErr == nil), - Service: c.ServiceAPID, + Service: serviceAPID, }) return nil } -func (c *Env) dotenvMethod(ctx context.Context, drv *ui.Driver, env map[string]string) error { +func (c *Env) dotenvMethod(ctx context.Context, drv *ui.Driver, env map[string]string, serviceAPID string) error { var b bytes.Buffer var keys []string @@ -258,14 +219,112 @@ func (c *Env) dotenvMethod(ctx context.Context, drv *ui.Driver, env map[string]s for _, key := range keys { fmt.Fprintf(&b, "%s=\"%s\"\n", key, env[key]) } - err := os.WriteFile(".env", b.Bytes(), 0644) - if err != nil { - return err - } + clipboardErr := clipboard.WriteAll(b.String()) drv.Activate(ctx, &models.EnvDotenv{ - Service: c.ServiceAPID, + InClipboard: (clipboardErr == nil), + Service: serviceAPID, }) return nil } + +func (c *Env) displayMethod(ctx context.Context, drv *ui.Driver, env map[string]string, serviceAPID string) error { + var b strings.Builder + + var keys []string + for key := range env { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + fmt.Fprintf(&b, "export %s=\"%s\"\n", key, env[key]) + } + + drv.Activate(ctx, &models.EnvDisplay{ + EnvString: b.String(), + Service: serviceAPID, + }) + + return nil +} + +func (c *Env) chainAPID() string { + if c.ChainAPID != "" { + return c.ChainAPID + } + + return "ca" +} + +func (c *Env) orgAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (string, error) { + if c.OrgAPID != "" { + return c.OrgAPID, nil + } + if cfg.Service.Env.Org != "" { + return cfg.Service.Env.Org, nil + } + + selector := &component.Selector[api.Organization]{ + Prompt: "Which organization's env do you want to fetch?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return c.Anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return org.Apid, nil +} + +func (c *Env) realmAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID string) (string, error) { + if c.RealmAPID != "" { + return c.RealmAPID, nil + } + if cfg.Service.Env.Realm != "" { + return cfg.Service.Env.Realm, nil + } + + selector := &component.Selector[api.Realm]{ + Prompt: fmt.Sprintf("Which %s realm's env do you want to fetch?", ui.Emphasize(orgAPID)), + Flag: "--realm", + + Fetcher: &component.Fetcher[api.Realm]{ + FetchFn: func() ([]api.Realm, error) { return c.Anc.GetOrgRealms(ctx, orgAPID) }, + }, + } + + realm, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return realm.Apid, nil +} + +func (c *Env) serviceAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID, realmAPID string) (string, error) { + if c.ServiceAPID != "" { + return c.ServiceAPID, nil + } + if cfg.Service.Env.Service != "" { + return cfg.Service.Env.Service, nil + } + + selector := &component.Selector[api.Service]{ + Prompt: fmt.Sprintf("Which %s/%s service do you want to fetch?", ui.Emphasize(orgAPID), ui.Emphasize(realmAPID)), + Flag: "--service", + + Fetcher: &component.Fetcher[api.Service]{ + FetchFn: func() ([]api.Service, error) { return c.Anc.GetOrgServices(ctx, orgAPID, api.NonDiagnosticServices) }, + }, + } + + service, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return service.Slug, nil +} diff --git a/service/env_test.go b/service/env_test.go index fa12ecc..daab588 100644 --- a/service/env_test.go +++ b/service/env_test.go @@ -62,6 +62,7 @@ func TestServiceEnv(t *testing.T) { defer cancel() cfg := new(cli.Config) + cfg.AnchorURL = "http://anchor.lcl.host" cfg.API.URL = srv.URL var err error if cfg.API.Token, err = srv.GeneratePAT("anky@anchor.dev"); err != nil { @@ -69,7 +70,7 @@ func TestServiceEnv(t *testing.T) { } ctx = cli.ContextWithConfig(ctx, cfg) - t.Run("basics clipboard", func(t *testing.T) { + t.Run("basics export", func(t *testing.T) { if srv.IsProxy() { t.Skip("service env unsupported in proxy mode") } @@ -79,8 +80,16 @@ func TestServiceEnv(t *testing.T) { errc := make(chan error, 1) go func() { - errc <- cmd.UI().RunTUI(ctx, drv) - errc <- tm.Quit() + defer close(errc) + + if err := cmd.UI().RunTUI(ctx, drv); err != nil { + errc <- err + return + } + if err := tm.Quit(); err != nil { + errc <- err + return + } }() uitest.WaitForGoldenContains(t, drv, errc, @@ -92,16 +101,17 @@ func TestServiceEnv(t *testing.T) { }) tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) + if err := <-errc; err != nil { + t.Fatal(err) + } env, err := clipboard.ReadAll() if err != nil { t.Fatal(err) } - want := "export ACME_CONTACT=\"anky@anchor.dev\"\nexport ACME_DIRECTORY_URL=\"/org-slug/realm-slug/x509/ca/acme\"\nexport ACME_HMAC_KEY=\"abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\nexport ACME_KID=\"aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF\"\nexport HTTPS_PORT=\"4433\"\nexport SERVER_NAMES=\"service.lcl.host\"\n" - got := env - - if want != got { + want := "export ACME_CONTACT=\"anky@anchor.dev\"\nexport ACME_DIRECTORY_URL=\"http://anchor.lcl.host/org-slug/realm-slug/x509/ca/acme\"\nexport ACME_HMAC_KEY=\"abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\nexport ACME_KID=\"aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF\"\nexport HTTPS_PORT=\"4433\"\nexport SERVER_NAMES=\"service.lcl.host\"\n" + if got := env; want != got { t.Errorf("Want env clipboard:\n\n%q,\n\nGot:\n\n%q\n\n", want, got) } @@ -113,20 +123,6 @@ func TestServiceEnv(t *testing.T) { t.Skip("service env unsupported in proxy mode") } - dir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - tmpDir, err := os.MkdirTemp("", "anchor-trust") - if err != nil { - t.Fatal(err) - } - err = os.Chdir(tmpDir) - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpDir) - drv, tm := uitest.TestTUI(ctx, t) cmd := Env{} errc := make(chan error, 1) @@ -148,25 +144,48 @@ func TestServiceEnv(t *testing.T) { }) tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) - - env, err := os.ReadFile(".env") - if err != nil { + if err := <-errc; err != nil { t.Fatal(err) } - err = os.Chdir(dir) + + env, err := clipboard.ReadAll() if err != nil { t.Fatal(err) } - if err := <-errc; err != nil { - t.Fatal(<-errc) + want := "ACME_CONTACT=\"anky@anchor.dev\"\nACME_DIRECTORY_URL=\"http://anchor.lcl.host/org-slug/realm-slug/x509/ca/acme\"\nACME_HMAC_KEY=\"abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\nACME_KID=\"aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF\"\nHTTPS_PORT=\"4433\"\nSERVER_NAMES=\"service.lcl.host\"\n" + if got := env; want != got { + t.Errorf("Want .env contents:\n\n%q,\n\nGot:\n\n%q\n\n", want, got) } - want := "ACME_CONTACT=\"anky@anchor.dev\"\nACME_DIRECTORY_URL=\"/org-slug/realm-slug/x509/ca/acme\"\nACME_HMAC_KEY=\"abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\nACME_KID=\"aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF\"\nHTTPS_PORT=\"4433\"\nSERVER_NAMES=\"service.lcl.host\"\n" - got := string(env) + uitest.TestGolden(t, drv.Golden()) + }) - if want != got { - t.Errorf("Want .env contents:\n\n%q,\n\nGot:\n\n%q\n\n", want, got) + t.Run("basics display", func(t *testing.T) { + if srv.IsProxy() { + t.Skip("service env unsupported in proxy mode") + } + + drv, tm := uitest.TestTUI(ctx, t) + cmd := Env{} + errc := make(chan error, 1) + + go func() { + errc <- cmd.UI().RunTUI(ctx, drv) + errc <- tm.Quit() + }() + + uitest.WaitForGoldenContains(t, drv, errc, + "? How would you like to manage your environment variables?", + ) + + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyDown}) + tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) + + tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3)) + if err := <-errc; err != nil { + t.Fatal(err) } uitest.TestGolden(t, drv.Golden()) diff --git a/service/models/env.go b/service/models/env.go index a287eba..2b2073c 100644 --- a/service/models/env.go +++ b/service/models/env.go @@ -21,7 +21,7 @@ var ( ServiceEnvHint = ui.Section{ Name: "ServiceEnvHint", Model: ui.MessageLines{ - ui.StepHint("Environment variables provide your configuration and credentials."), + ui.StepHint("We'll set your environment variables to provide configuration and credentials."), }, } ) @@ -63,8 +63,6 @@ func (m *EnvFetch) View() string { return b.String() } - fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf("Fetched %s environment variables.", ui.Emphasize(m.Service)))) - return b.String() } @@ -78,12 +76,16 @@ type EnvMethod struct { func (m *EnvMethod) Init() tea.Cmd { m.list = ui.List([]ui.ListItem[string]{ { - Key: "clipboard", - String: "Add to your clipboard", + Key: "export", + String: "Add export commands to your clipboard.", }, { Key: "dotenv", - String: "Write to .env file", + String: "Add dotenv contents to your clipboard.", + }, + { + Key: "display", + String: "Display export commands. ! WARNING: could be observed by others.", }, }) return nil @@ -122,7 +124,12 @@ func (m *EnvMethod) View() string { return b.String() } - fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf("Entered %s environment variable management.", ui.Emphasize(m.choice)))) + fmt.Fprintln(&b, ui.StepDone( + fmt.Sprintf("Selected %s environment variable method. %s", + ui.Emphasize(m.choice), + ui.Whisper(fmt.Sprintf("You can also use `--method %s`.", m.choice)), + ), + )) return b.String() } @@ -140,21 +147,22 @@ func (m *EnvClipboard) View() string { if !m.InClipboard { // FIXME: handling for clipboard errors - fmt.Fprintln(&b, ui.StepAlert("Unable to copy env to your clipboard.")) + fmt.Fprintln(&b, ui.StepAlert("Unable to copy export commands to your clipboard.")) } fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf( - "Copied %s env to your clipboard.", + "Copied %s export commands to your clipboard.", ui.Emphasize(m.Service)))) - fmt.Fprintln(&b, ui.StepAlert(fmt.Sprintf("%s to load env in current session.", + fmt.Fprintln(&b, ui.StepAlert(fmt.Sprintf("%s to load your environment variables.", ui.Action("Paste and press enter")))) return b.String() } type EnvDotenv struct { - Service string + InClipboard bool + Service string } func (m *EnvDotenv) Init() tea.Cmd { return nil } @@ -164,10 +172,40 @@ func (m *EnvDotenv) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil } func (m *EnvDotenv) View() string { var b strings.Builder + if !m.InClipboard { + // FIXME: handling for clipboard errors + fmt.Fprintln(&b, ui.StepAlert("Unable to copy dotenv contents to your clipboard.")) + } + fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf( - "Wrote %s env to %s.", - ui.Emphasize(m.Service), - ui.Whisper("`.env`")))) + "Copied %s dotenv contents to your clipboard.", + ui.Emphasize(m.Service)))) + + fmt.Fprintln(&b, ui.StepAlert(fmt.Sprintf("%s into your dotenv so your server will find them next restart.", + ui.Action("Paste")))) + + return b.String() +} + +type EnvDisplay struct { + EnvString string + Service string +} + +func (m *EnvDisplay) Init() tea.Cmd { return nil } + +func (m *EnvDisplay) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil } + +func (m *EnvDisplay) View() string { + var b strings.Builder + + fmt.Fprintf(&b, "\n%s\n", m.EnvString) + + fmt.Fprintln(&b, ui.StepDone(fmt.Sprintf( + "Displayed %s export commands.", + ui.Emphasize(m.Service)))) + + fmt.Fprintln(&b, ui.StepAlert("Be sure to load these into your environment.")) return b.String() } @@ -184,8 +222,9 @@ func (m *EnvNextSteps) View() string { var b strings.Builder fmt.Fprintln(&b, ui.Header("Next Steps")) - fmt.Fprintln(&b, ui.StepNext(fmt.Sprintf("(Re)Start your server and check out your encrypted site at: %s", ui.URL(m.LclUrl)))) - fmt.Fprintln(&b, ui.StepNext("These certificates will renew automatically, time to enjoy effortless encryption.")) + fmt.Fprintln(&b, ui.StepAlert(ui.Action("(Re)Start your server."))) + fmt.Fprintln(&b, ui.StepAlert(fmt.Sprintf("%s: %s", ui.Action("Check out your encrypted site"), ui.URL(m.LclUrl)))) + fmt.Fprintln(&b, ui.StepHint("These certificates will renew automatically, time to enjoy effortless encryption.")) return b.String() } diff --git a/service/testdata/TestServiceEnv/basics_display.golden b/service/testdata/TestServiceEnv/basics_display.golden new file mode 100644 index 0000000..99c3cad --- /dev/null +++ b/service/testdata/TestServiceEnv/basics_display.golden @@ -0,0 +1,144 @@ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: probing credentials locally…⠋ +─── Client ───────────────────────────────────────────────────────────────────── + * Checking authentication: testing credentials remotely…⠋ +─── ServiceEnvHeader ─────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` +─── ServiceEnvHint ───────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + * Fetching organizations…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + * Fetching realms…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + * Fetching services…⠋ +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. +─── EnvFetch ─────────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. + * Fetching service-name environment variables…⠋ +─── EnvFetch ─────────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. + ? How would you like to manage your environment variables? + > Add export commands to your clipboard. + Add dotenv contents to your clipboard. + Display export commands. ! WARNING: could be observed by others. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. + ? How would you like to manage your environment variables? + Add export commands to your clipboard. + > Add dotenv contents to your clipboard. + Display export commands. ! WARNING: could be observed by others. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. + ? How would you like to manage your environment variables? + Add export commands to your clipboard. + Add dotenv contents to your clipboard. + > Display export commands. ! WARNING: could be observed by others. +─── EnvMethod ────────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. + - Selected display environment variable method. You can also use `--method display`. +─── EnvDisplay ───────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. + - Selected display environment variable method. You can also use `--method display`. + +export ACME_CONTACT="anky@anchor.dev" +export ACME_DIRECTORY_URL="http://anchor.lcl.host/org-slug/realm-slug/x509/ca/acme" +export ACME_HMAC_KEY="abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ" +export ACME_KID="aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF" +export HTTPS_PORT="4433" +export SERVER_NAMES="service.lcl.host" + + - Displayed service-name export commands. + ! Be sure to load these into your environment. +─── EnvNextSteps ─────────────────────────────────────────────────────────────── + +# Fetch Environment Variables for Service `anchor service env` + | We'll set your environment variables to provide configuration and credentials. + - Using org-slug, the only available organization. You can also use `--org org-slug`. + - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. + - Using service-name, the only available service. You can also use `--service service-name`. + - Selected display environment variable method. You can also use `--method display`. + +export ACME_CONTACT="anky@anchor.dev" +export ACME_DIRECTORY_URL="http://anchor.lcl.host/org-slug/realm-slug/x509/ca/acme" +export ACME_HMAC_KEY="abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ" +export ACME_KID="aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF" +export HTTPS_PORT="4433" +export SERVER_NAMES="service.lcl.host" + + - Displayed service-name export commands. + ! Be sure to load these into your environment. + +# Next Steps + ! (Re)Start your server. + ! Check out your encrypted site: https://service.lcl.host:4433 + | These certificates will renew automatically, time to enjoy effortless encryption. diff --git a/service/testdata/TestServiceEnv/basics_dotenv.golden b/service/testdata/TestServiceEnv/basics_dotenv.golden index 38b9b0a..973b24d 100644 --- a/service/testdata/TestServiceEnv/basics_dotenv.golden +++ b/service/testdata/TestServiceEnv/basics_dotenv.golden @@ -3,100 +3,115 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── ServiceEnvHeader ─────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` ─── ServiceEnvHint ───────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… + | We'll set your environment variables to provide configuration and credentials. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. * Fetching organizations…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. * Fetching realms…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Service,github.com/anchordo… +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. * Fetching services…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Service,github.com/anchordo… +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. ─── EnvFetch ─────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. * Fetching service-name environment variables…⠋ ─── EnvFetch ─────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. ─── EnvMethod ────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. ? How would you like to manage your environment variables? - > Add to your clipboard - Write to .env file + > Add export commands to your clipboard. + Add dotenv contents to your clipboard. + Display export commands. ! WARNING: could be observed by others. ─── EnvMethod ────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. ? How would you like to manage your environment variables? - Add to your clipboard - > Write to .env file + Add export commands to your clipboard. + > Add dotenv contents to your clipboard. + Display export commands. ! WARNING: could be observed by others. ─── EnvMethod ────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. - - Entered dotenv environment variable management. + - Selected dotenv environment variable method. You can also use `--method dotenv`. ─── EnvDotenv ────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. - - Entered dotenv environment variable management. - - Wrote service-name env to `.env`. + - Selected dotenv environment variable method. You can also use `--method dotenv`. + - Copied service-name dotenv contents to your clipboard. + ! Paste into your dotenv so your server will find them next restart. ─── EnvNextSteps ─────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. - - Entered dotenv environment variable management. - - Wrote service-name env to `.env`. + - Selected dotenv environment variable method. You can also use `--method dotenv`. + - Copied service-name dotenv contents to your clipboard. + ! Paste into your dotenv so your server will find them next restart. + # Next Steps - - (Re)Start your server and check out your encrypted site at: https://service.lcl.host:4433 - - These certificates will renew automatically, time to enjoy effortless encryption. + ! (Re)Start your server. + ! Check out your encrypted site: https://service.lcl.host:4433 + | These certificates will renew automatically, time to enjoy effortless encryption. diff --git a/service/testdata/TestServiceEnv/basics_clipboard.golden b/service/testdata/TestServiceEnv/basics_export.golden similarity index 61% rename from service/testdata/TestServiceEnv/basics_clipboard.golden rename to service/testdata/TestServiceEnv/basics_export.golden index 348ce00..069724e 100644 --- a/service/testdata/TestServiceEnv/basics_clipboard.golden +++ b/service/testdata/TestServiceEnv/basics_export.golden @@ -3,92 +3,104 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── ServiceEnvHeader ─────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` ─── ServiceEnvHint ───────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… + | We'll set your environment variables to provide configuration and credentials. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. * Fetching organizations…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. * Fetching realms…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Service,github.com/anchordo… +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. * Fetching services…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Service,github.com/anchordo… +─── Fetcher[github.com/anchordotdev/cli/api.Service] ─────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. ─── EnvFetch ─────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. * Fetching service-name environment variables…⠋ ─── EnvFetch ─────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. ─── EnvMethod ────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. ? How would you like to manage your environment variables? - > Add to your clipboard - Write to .env file + > Add export commands to your clipboard. + Add dotenv contents to your clipboard. + Display export commands. ! WARNING: could be observed by others. ─── EnvMethod ────────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. - - Entered clipboard environment variable management. + - Selected export environment variable method. You can also use `--method export`. ─── EnvClipboard ─────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. - - Entered clipboard environment variable management. - - Copied service-name env to your clipboard. - ! Paste and press enter to load env in current session. + - Selected export environment variable method. You can also use `--method export`. + - Copied service-name export commands to your clipboard. + ! Paste and press enter to load your environment variables. ─── EnvNextSteps ─────────────────────────────────────────────────────────────── + # Fetch Environment Variables for Service `anchor service env` - | Environment variables provide your configuration and credentials. + | We'll set your environment variables to provide configuration and credentials. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Using service-name, the only available service. You can also use `--service service-name`. - - Fetched service-name environment variables. - - Entered clipboard environment variable management. - - Copied service-name env to your clipboard. - ! Paste and press enter to load env in current session. + - Selected export environment variable method. You can also use `--method export`. + - Copied service-name export commands to your clipboard. + ! Paste and press enter to load your environment variables. + # Next Steps - - (Re)Start your server and check out your encrypted site at: https://service.lcl.host:4433 - - These certificates will renew automatically, time to enjoy effortless encryption. + ! (Re)Start your server. + ! Check out your encrypted site: https://service.lcl.host:4433 + | These certificates will renew automatically, time to enjoy effortless encryption. diff --git a/testdata/TestError/golden-unix.golden b/testdata/TestError/golden-unix.golden index fd037d6..61e0ee2 100644 --- a/testdata/TestError/golden-unix.golden +++ b/testdata/TestError/golden-unix.golden @@ -1,19 +1,25 @@ ─── TestHeader ───────────────────────────────────────────────────────────────── + # Test error `anchor test error` ─── TestHint ─────────────────────────────────────────────────────────────────── + # Test error `anchor test error` | Test error Hint. ─── ReportError ──────────────────────────────────────────────────────────────── + # Test error `anchor test error` | Test error Hint. + # Error! test error `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ─── Browserless ──────────────────────────────────────────────────────────────── + # Test error `anchor test error` | Test error Hint. + # Error! test error `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ! Warning: Unable to open browser. - ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60%2Ftmp%2Fgo-build0123456789%2Fb001%2Fexe%2Fanchor%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A%23+Test+error+%60anchor+test+error%60%0A++++%7C+Test+error+Hint.%0A%60%60%60%0A&title=Error%3A+test+error. + ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60%2Ftmp%2Fgo-build0123456789%2Fb001%2Fexe%2Fanchor%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A++++++++++++++++++++++++++++++++%0A%23+Test+error+%60anchor+test+error%60%0A++++%7C+Test+error+Hint.%0A%60%60%60%0A&title=Error%3A+test+error. diff --git a/testdata/TestError/golden-windows.golden b/testdata/TestError/golden-windows.golden index 072e37c..7b4ef48 100644 --- a/testdata/TestError/golden-windows.golden +++ b/testdata/TestError/golden-windows.golden @@ -1,19 +1,25 @@ ─── TestHeader ───────────────────────────────────────────────────────────────── + # Test error `anchor test error` ─── TestHint ─────────────────────────────────────────────────────────────────── + # Test error `anchor test error` | Test error Hint. ─── ReportError ──────────────────────────────────────────────────────────────── + # Test error `anchor test error` | Test error Hint. + # Error! test error `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ─── Browserless ──────────────────────────────────────────────────────────────── + # Test error `anchor test error` | Test error Hint. + # Error! test error `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ! Warning: Unable to open browser. - ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60C%3A%5CUsers%5Cusername%5CAppData%5CLocal%5CTemp%5Cgo-build0123456789%2Fb001%2Fexe%2Fanchor.exe%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A%23+Test+error+%60anchor+test+error%60%0A++++%7C+Test+error+Hint.%0A%60%60%60%0A&title=Error%3A+test+error. + ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60C%3A%5CUsers%5Cusername%5CAppData%5CLocal%5CTemp%5Cgo-build0123456789%2Fb001%2Fexe%2Fanchor.exe%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A++++++++++++++++++++++++++++++++%0A%23+Test+error+%60anchor+test+error%60%0A++++%7C+Test+error+Hint.%0A%60%60%60%0A&title=Error%3A+test+error. diff --git a/testdata/TestPanic/golden-unix.golden b/testdata/TestPanic/golden-unix.golden index 079c788..f30e39d 100644 --- a/testdata/TestPanic/golden-unix.golden +++ b/testdata/TestPanic/golden-unix.golden @@ -1,19 +1,25 @@ ─── TestHeader ───────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` ─── TestHint ─────────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` | Test panic Hint. ─── ReportError ──────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` | Test panic Hint. + # Error! test panic `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ─── Browserless ──────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` | Test panic Hint. + # Error! test panic `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ! Warning: Unable to open browser. - ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60%2Ftmp%2Fgo-build0123456789%2Fb001%2Fexe%2Fanchor%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStack%3A%2A%2A%0A%60%60%60%0Apanic%28%7B%3Chex%3E%2C+%3Chex%3E%7D%29%0A%09%3Cgoroot%3E%2Fsrc%2Fruntime%2Fpanic.go%3A%3Cline%3E+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.%28%2APanicCommand%29.run%28%3Chex%3E%2C+%7B%3Chex%3E%2C+%3Chex%3E%7D%2C+%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A108+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1.1%28%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli%2Fstacktrace.CapturePanic%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fstacktrace%2Fstacktrace.go%3A40+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Atesting.tRunner%28%3Chex%3E%2C+%3Chex%3E%29%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0Acreated+by+testing.%28%2AT%29.Run+in+gouroutine+%3Cint%3E%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0A%60%60%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A%23+Test+panic+%60anchor+test+panic%60%0A++++%7C+Test+panic+Hint.%0A%60%60%60%0A&title=Error%3A+test+panic. + ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60%2Ftmp%2Fgo-build0123456789%2Fb001%2Fexe%2Fanchor%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStack%3A%2A%2A%0A%60%60%60%0Apanic%28%7B%3Chex%3E%2C+%3Chex%3E%7D%29%0A%09%3Cgoroot%3E%2Fsrc%2Fruntime%2Fpanic.go%3A%3Cline%3E+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.%28%2APanicCommand%29.run%28%3Chex%3E%2C+%7B%3Chex%3E%2C+%3Chex%3E%7D%2C+%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A108+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1.1%28%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli%2Fstacktrace.CapturePanic%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fstacktrace%2Fstacktrace.go%3A40+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Atesting.tRunner%28%3Chex%3E%2C+%3Chex%3E%29%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0Acreated+by+testing.%28%2AT%29.Run+in+gouroutine+%3Cint%3E%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0A%60%60%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A++++++++++++++++++++++++++++++++%0A%23+Test+panic+%60anchor+test+panic%60%0A++++%7C+Test+panic+Hint.%0A%60%60%60%0A&title=Error%3A+test+panic. diff --git a/testdata/TestPanic/golden-windows.golden b/testdata/TestPanic/golden-windows.golden index 5d48117..929bbc6 100644 --- a/testdata/TestPanic/golden-windows.golden +++ b/testdata/TestPanic/golden-windows.golden @@ -1,19 +1,25 @@ ─── TestHeader ───────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` ─── TestHint ─────────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` | Test panic Hint. ─── ReportError ──────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` | Test panic Hint. + # Error! test panic `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ─── Browserless ──────────────────────────────────────────────────────────────── + # Test panic `anchor test panic` | Test panic Hint. + # Error! test panic `` | We are sorry you encountered this error. ! Press Enter to open an issue on Github. ! Warning: Unable to open browser. - ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60C%3A%5CUsers%5Cusername%5CAppData%5CLocal%5CTemp%5Cgo-build0123456789%2Fb001%2Fexe%2Fanchor.exe%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStack%3A%2A%2A%0A%60%60%60%0Apanic%28%7B%3Chex%3E%2C+%3Chex%3E%7D%29%0A%09%3Cgoroot%3E%2Fsrc%2Fruntime%2Fpanic.go%3A%3Cline%3E+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.%28%2APanicCommand%29.run%28%3Chex%3E%2C+%7B%3Chex%3E%2C+%3Chex%3E%7D%2C+%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A108+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1.1%28%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli%2Fstacktrace.CapturePanic%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fstacktrace%2Fstacktrace.go%3A40+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Atesting.tRunner%28%3Chex%3E%2C+%3Chex%3E%29%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0Acreated+by+testing.%28%2AT%29.Run+in+gouroutine+%3Cint%3E%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0A%60%60%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A%23+Test+panic+%60anchor+test+panic%60%0A++++%7C+Test+panic+Hint.%0A%60%60%60%0A&title=Error%3A+test+panic. + ! Open this in a browser to continue: https://github.com/anchordotdev/cli/issues/new?body=%2A%2AAre+there+any+additional+details+you+would+like+to+share%3F%2A%2A%0A%0A---%0A%0A%2A%2ACommand%3A%2A%2A+%60anchor%60%0A%2A%2AExecutable%3A%2A%2A+%60C%3A%5CUsers%5Cusername%5CAppData%5CLocal%5CTemp%5Cgo-build0123456789%2Fb001%2Fexe%2Fanchor.exe%60%0A%2A%2AVersion%3A%2A%2A+%60dev+%28goos%2Fgoarch%29+Commit%3A+none+BuildDate%3A+unknown%60%0A%2A%2AArguments%3A%2A%2A+%60%5B%5D%60%0A%2A%2AFlags%3A%2A%2A+%60%5B%5D%60%0A%2A%2ATimestamp%3A%2A%2A+%602024-01-02T15%3A04%3A05.987654321Z%60%0A%2A%2AStack%3A%2A%2A%0A%60%60%60%0Apanic%28%7B%3Chex%3E%2C+%3Chex%3E%7D%29%0A%09%3Cgoroot%3E%2Fsrc%2Fruntime%2Fpanic.go%3A%3Cline%3E+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.%28%2APanicCommand%29.run%28%3Chex%3E%2C+%7B%3Chex%3E%2C+%3Chex%3E%7D%2C+%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A108+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1.1%28%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli%2Fstacktrace.CapturePanic%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fstacktrace%2Fstacktrace.go%3A40+%2B%3Chex%3E%0Agithub.com%2Fanchordotdev%2Fcli_test.TestPanic.func1%28%3Chex%3E%29%0A%09%3Cpwd%3E%2Fcli_test.go%3A129+%2B%3Chex%3E%0Atesting.tRunner%28%3Chex%3E%2C+%3Chex%3E%29%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0Acreated+by+testing.%28%2AT%29.Run+in+gouroutine+%3Cint%3E%0A%09%3Cgoroot%3E%2Fsrc%2Ftesting%2Ftesting.go%3A%3Cline%3E+%2B%3Chex%3E%0A%60%60%60%0A%2A%2AStdout%3A%2A%2A%0A%60%60%60%0A++++++++++++++++++++++++++++++++%0A%23+Test+panic+%60anchor+test+panic%60%0A++++%7C+Test+panic+Hint.%0A%60%60%60%0A&title=Error%3A+test+panic. diff --git a/trust/clean.go b/trust/clean.go index a53290d..756d6ca 100644 --- a/trust/clean.go +++ b/trust/clean.go @@ -2,7 +2,9 @@ package trust import ( "context" + "fmt" "os" + "strings" "github.com/anchordotdev/cli" "github.com/anchordotdev/cli/api" @@ -144,7 +146,7 @@ func (c Clean) Perform(ctx context.Context, drv *ui.Driver) error { drv.Send(models.CACleaningMsg{Store: store}) if _, err := store.UninstallCA(ca); err != nil { - return err + return classifyError(err) } drv.Send(models.CACleanedMsg{Store: store}) @@ -153,3 +155,19 @@ func (c Clean) Perform(ctx context.Context, drv *ui.Driver) error { return nil } + +func classifyError(err error) error { + // TODO: should these be a ui.Error's? + switch { + case strings.HasSuffix(err.Error(), "sudo: 3 incorrect password attempts"): + return cli.UserError{ + Err: fmt.Errorf("sudo failed: invalid password, please try again with the correct password."), + } + case strings.HasSuffix(strings.TrimSpace(err.Error()), "SecTrustSettingsRemoveTrustSettings: The authorization was canceled by the user."): + return cli.UserError{ + Err: fmt.Errorf("remove cert failed: action canceled."), + } + default: + return err + } +} diff --git a/trust/models/audit.go b/trust/models/audit.go index bcb1e32..f2dd315 100644 --- a/trust/models/audit.go +++ b/trust/models/audit.go @@ -21,7 +21,7 @@ var ( TrustAuditHint = ui.Section{ Name: "TrustAuditHint", Model: ui.MessageLines{ - ui.StepHint("We will compare your CA certificates from Anchor and your local trust stores."), + ui.StepHint("We'll compare your CA certificates from Anchor and your local trust stores."), }, } ) diff --git a/trust/models/clean.go b/trust/models/clean.go index 1859c0d..a00e756 100644 --- a/trust/models/clean.go +++ b/trust/models/clean.go @@ -21,28 +21,18 @@ var TrustCleanHeader = ui.Section{ type TrustCleanHint struct { CertStates, TrustStores []string - - spinner spinner.Model } -func (c *TrustCleanHint) Init() tea.Cmd { - c.spinner = ui.WaitingSpinner() +func (c *TrustCleanHint) Init() tea.Cmd { return nil } - return c.spinner.Tick -} - -func (c *TrustCleanHint) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var cmd tea.Cmd - c.spinner, cmd = c.spinner.Update(msg) - return c, cmd -} +func (c *TrustCleanHint) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return c, nil } func (c *TrustCleanHint) View() string { states := strings.Join(c.CertStates, ", ") stores := strings.Join(c.TrustStores, ", ") var b strings.Builder - fmt.Fprintln(&b, ui.Hint(fmt.Sprintf("Removing %s CA certificates from the %s store(s).", states, stores))) + fmt.Fprintln(&b, ui.Hint(fmt.Sprintf("We'll remove %s CA certificates from the %s store(s).", states, stores))) return b.String() } diff --git a/trust/models/trust.go b/trust/models/trust.go index 01cc06c..fa1343d 100644 --- a/trust/models/trust.go +++ b/trust/models/trust.go @@ -22,7 +22,7 @@ var ( TrustHint = ui.Section{ Name: "TrustHint", Model: ui.MessageLines{ - ui.StepHint("We will check your local trust stores, then make any needed updates."), + ui.StepHint("We'll check your local trust stores and make any needed updates."), }, } ) diff --git a/trust/testdata/TestAudit/expected,_missing,_and_extra_CAs.golden b/trust/testdata/TestAudit/expected,_missing,_and_extra_CAs.golden index cd3cc2b..3091c60 100644 --- a/trust/testdata/TestAudit/expected,_missing,_and_extra_CAs.golden +++ b/trust/testdata/TestAudit/expected,_missing,_and_extra_CAs.golden @@ -3,21 +3,26 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── TrustAuditHeader ─────────────────────────────────────────────────────────── + # Audit CA Certificates in Your Local Trust Store(s) `anchor trust audit` ─── TrustAuditHint ───────────────────────────────────────────────────────────── + # Audit CA Certificates in Your Local Trust Store(s) `anchor trust audit` - | We will compare your CA certificates from Anchor and your local trust stores. + | We'll compare your CA certificates from Anchor and your local trust stores. ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Audit CA Certificates in Your Local Trust Store(s) `anchor trust audit` - | We will compare your CA certificates from Anchor and your local trust stores. + | We'll compare your CA certificates from Anchor and your local trust stores. * Comparing local and expected CA certificates…⠋ ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Audit CA Certificates in Your Local Trust Store(s) `anchor trust audit` - | We will compare your CA certificates from Anchor and your local trust stores. + | We'll compare your CA certificates from Anchor and your local trust stores. - Compared local and expected CA certificates: need to install 1 missing certificates. ─── TrustAuditInfo ───────────────────────────────────────────────────────────── + # Audit CA Certificates in Your Local Trust Store(s) `anchor trust audit` - | We will compare your CA certificates from Anchor and your local trust stores. + | We'll compare your CA certificates from Anchor and your local trust stores. - Compared local and expected CA certificates: need to install 1 missing certificates. - VALID - oas-examples - AnchorCA ECDSA: trusted by [Mock] - MISSING - oas-examples - AnchorCA RSA: missing from [Mock] diff --git a/trust/testdata/TestClean/basics.golden b/trust/testdata/TestClean/basics.golden index abfac2f..8e54395 100644 --- a/trust/testdata/TestClean/basics.golden +++ b/trust/testdata/TestClean/basics.golden @@ -3,15 +3,19 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── TrustCleanHeader ─────────────────────────────────────────────────────────── + # Clean CA Certificates from Local Trust Store(s) `anchor trust clean` ─── TrustCleanHint ───────────────────────────────────────────────────────────── + # Clean CA Certificates from Local Trust Store(s) `anchor trust clean` -| Removing CA certificates from the mock store(s). +| We'll remove CA certificates from the mock store(s). ─── TrustCleanAudit ──────────────────────────────────────────────────────────── + # Clean CA Certificates from Local Trust Store(s) `anchor trust clean` -| Removing CA certificates from the mock store(s). +| We'll remove CA certificates from the mock store(s). * Auditing local CA certificates…⠋ ─── TrustCleanAudit ──────────────────────────────────────────────────────────── + # Clean CA Certificates from Local Trust Store(s) `anchor trust clean` -| Removing CA certificates from the mock store(s). +| We'll remove CA certificates from the mock store(s). - Audited local CA certificates: need to remove 0 certificates. diff --git a/trust/testdata/TestTrust/basics-unix.golden b/trust/testdata/TestTrust/basics-unix.golden index 650373e..05795a2 100644 --- a/trust/testdata/TestTrust/basics-unix.golden +++ b/trust/testdata/TestTrust/basics-unix.golden @@ -3,79 +3,93 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── TrustHeader ──────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` ─── TrustHint ────────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… + | We'll check your local trust stores and make any needed updates. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. * Fetching organizations…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. * Fetching realms…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. * Comparing local and expected CA certificates…⠋ ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. | Updates may require sudo privileges, learn why here: https://lcl.host/why-sudo ! Press Enter to install missing certificates. (requires sudo) ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. * Updating Mock: installing oas-examples - AnchorCA ECDSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed oas-examples - AnchorCA [ECDSA] ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed oas-examples - AnchorCA [ECDSA] * Updating Mock: installing oas-examples - AnchorCA RSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. diff --git a/trust/testdata/TestTrust/basics-windows.golden b/trust/testdata/TestTrust/basics-windows.golden index 697b0e6..eb3efa8 100644 --- a/trust/testdata/TestTrust/basics-windows.golden +++ b/trust/testdata/TestTrust/basics-windows.golden @@ -3,72 +3,85 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── TrustHeader ──────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` ─── TrustHint ────────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… + | We'll check your local trust stores and make any needed updates. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. * Fetching organizations…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. * Fetching realms…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. * Comparing local and expected CA certificates…⠋ ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. | Updates may require sudo privileges, learn why here: https://lcl.host/why-sudo ! Press Enter to install missing certificates. (requires sudo) ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. | "oas-examples - AnchorCA" Thumbprint (sha1): BA470EAC 5067C499 99F3F5A1 ACE9E8CA 48E2731C * Updating Mock: installing oas-examples - AnchorCA ECDSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed oas-examples - AnchorCA [ECDSA] ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. @@ -76,8 +89,9 @@ | "oas-examples - AnchorCA" Thumbprint (sha1): E1CE91B0 FC124890 24F7583B 8F0844EE 2291BE47 * Updating Mock: installing oas-examples - AnchorCA RSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. diff --git a/trust/testdata/TestTrust/noop.golden b/trust/testdata/TestTrust/noop.golden index 5667391..31e9fd2 100644 --- a/trust/testdata/TestTrust/noop.golden +++ b/trust/testdata/TestTrust/noop.golden @@ -3,37 +3,45 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── TrustHeader ──────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` ─── TrustHint ────────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… + | We'll check your local trust stores and make any needed updates. +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. * Fetching organizations…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. * Fetching realms…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. * Comparing local and expected CA certificates…⠋ ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: no updates needed. diff --git a/trust/testdata/TestTrust/wsl-vm.golden b/trust/testdata/TestTrust/wsl-vm.golden index ac8fe62..015bdbd 100644 --- a/trust/testdata/TestTrust/wsl-vm.golden +++ b/trust/testdata/TestTrust/wsl-vm.golden @@ -3,49 +3,57 @@ ─── Client ───────────────────────────────────────────────────────────────────── * Checking authentication: testing credentials remotely…⠋ ─── TrustHeader ──────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` ─── TrustHint ────────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ─── VMHint ───────────────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup * Fetching organizations…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Organization,github.com/anc… +─── Fetcher[github.com/anchordotdev/cli/api.Organization] ────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup - Using org-slug, the only available organization. You can also use `--org org-slug`. -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup - Using org-slug, the only available organization. You can also use `--org org-slug`. * Fetching realms…⠋ -─── SelectorFetcher[github.com/anchordotdev/cli/api.Realm,github.com/anchordotd… +─── Fetcher[github.com/anchordotdev/cli/api.Realm] ───────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup - Using org-slug, the only available organization. You can also use `--org org-slug`. - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup @@ -53,8 +61,9 @@ - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. * Comparing local and expected CA certificates…⠋ ─── TrustStoreAudit ──────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup @@ -62,8 +71,9 @@ - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup @@ -73,8 +83,9 @@ | Updates may require sudo privileges, learn why here: https://lcl.host/why-sudo ! Press Enter to install missing certificates. (requires sudo) ─── TrustUpdateConfirm ───────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup @@ -82,8 +93,9 @@ - Using realm-slug, the only available realm. You can also use `--realm realm-slug`. - Compared local and expected CA certificates: need to install 2 missing certificates. ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup @@ -92,8 +104,9 @@ - Compared local and expected CA certificates: need to install 2 missing certificates. * Updating Mock: installing oas-examples - AnchorCA ECDSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup @@ -102,8 +115,9 @@ - Compared local and expected CA certificates: need to install 2 missing certificates. - Updated Mock: installed oas-examples - AnchorCA [ECDSA] ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup @@ -113,8 +127,9 @@ - Updated Mock: installed oas-examples - AnchorCA [ECDSA] * Updating Mock: installing oas-examples - AnchorCA RSA… ⠋ ─── TrustUpdateStore ─────────────────────────────────────────────────────────── + # Manage CA Certificates in your Local Trust Store(s) `anchor trust` - | We will check your local trust stores, then make any needed updates. + | We'll check your local trust stores and make any needed updates. ! Warning: Running trust inside a VM or container will not update the host system. | Rerun this command on your host system to update it's trust stores and enable | secure communication, learn more here: https://cl.host/vm-container-setup diff --git a/trust/trust.go b/trust/trust.go index f9866d5..1749c73 100644 --- a/trust/trust.go +++ b/trust/trust.go @@ -75,45 +75,19 @@ func (c *Command) Perform(ctx context.Context, drv *ui.Driver) error { drv.Activate(ctx, &models.VMHint{}) } - if c.OrgSlug == "" { - c.OrgSlug = cfg.Trust.Org - } - if c.OrgSlug == "" { - choicec, err := component.OrgSelector(ctx, drv, c.Anc, - "Which organization do you want to trust?", - ) - if err != nil { - return err - } - select { - case org := <-choicec: - c.OrgSlug = org.Slug - case <-ctx.Done(): - return ctx.Err() - } + orgSlug, err := c.orgSlug(ctx, cfg, drv) + if err != nil { + return err } - if c.RealmSlug == "" { - c.RealmSlug = cfg.Trust.Realm - } - if c.RealmSlug == "" { - choicec, err := component.RealmSelector(ctx, drv, c.Anc, c.OrgSlug, - fmt.Sprintf("Which %s realm do you want to trust?", ui.Emphasize(c.OrgSlug)), - ) - if err != nil { - return err - } - select { - case realm := <-choicec: - c.RealmSlug = realm.Slug - case <-ctx.Done(): - return ctx.Err() - } + realmSlug, err := c.realmSlug(ctx, cfg, drv, orgSlug) + if err != nil { + return err } drv.Activate(ctx, &truststoremodels.TrustStoreAudit{}) - cas, err := fetchExpectedCAs(ctx, c.Anc, c.OrgSlug, c.RealmSlug) + cas, err := fetchExpectedCAs(ctx, c.Anc, orgSlug, realmSlug) if err != nil { return err } @@ -182,7 +156,7 @@ func (c *Command) Perform(ctx context.Context, drv *ui.Driver) error { } drv.Send(models.TrustStoreInstallingCAMsg{CA: *ca}) if ok, err := store.InstallCA(ca); err != nil { - return err + return classifyError(err) } else if !ok { panic("impossible") } @@ -193,6 +167,55 @@ func (c *Command) Perform(ctx context.Context, drv *ui.Driver) error { return nil } +func (c *Command) orgSlug(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (string, error) { + if c.OrgSlug != "" { + return c.OrgSlug, nil + } + if cfg.Trust.Org != "" { + return cfg.Trust.Org, nil + } + + selector := &component.Selector[api.Organization]{ + Prompt: "Which organization do you want to trust?", + Flag: "--org", + + Fetcher: &component.Fetcher[api.Organization]{ + FetchFn: func() ([]api.Organization, error) { return c.Anc.GetOrgs(ctx) }, + }, + } + + org, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return org.Apid, nil +} + +func (c *Command) realmSlug(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgSlug string) (string, error) { + if c.RealmSlug != "" { + return c.RealmSlug, nil + } + if cfg.Trust.Realm != "" { + return cfg.Trust.Realm, nil + } + + selector := &component.Selector[api.Realm]{ + + Prompt: fmt.Sprintf("Which %s realm do you want to trust?", ui.Emphasize(orgSlug)), + Flag: "--realm", + + Fetcher: &component.Fetcher[api.Realm]{ + FetchFn: func() ([]api.Realm, error) { return c.Anc.GetOrgRealms(ctx, orgSlug) }, + }, + } + + realm, err := selector.Choice(ctx, drv) + if err != nil { + return "", err + } + return realm.Apid, nil +} + func fetchOrgAndRealm(ctx context.Context, anc *api.Session) (string, string, error) { cfg := cli.ConfigFromContext(ctx) diff --git a/trust/trust_test.go b/trust/trust_test.go index 0606c62..56da1dd 100644 --- a/trust/trust_test.go +++ b/trust/trust_test.go @@ -110,8 +110,12 @@ func TestTrust(t *testing.T) { errc := make(chan error, 1) go func() { - errc <- cmd.UI().RunTUI(ctx, drv) + defer close(errc) + if err := cmd.UI().RunTUI(ctx, drv); err != nil { + errc <- err + return + } errc <- tm.Quit() }() @@ -140,8 +144,12 @@ func TestTrust(t *testing.T) { errc := make(chan error, 1) go func() { - errc <- cmd.UI().RunTUI(ctx, drv) + defer close(errc) + if err := cmd.UI().RunTUI(ctx, drv); err != nil { + errc <- err + return + } errc <- tm.Quit() }() @@ -176,9 +184,13 @@ func TestTrust(t *testing.T) { errc := make(chan error, 1) go func() { - errc <- cmd.UI().RunTUI(ctx, drv) + defer close(errc) - tm.Quit() + if err := cmd.UI().RunTUI(ctx, drv); err != nil { + errc <- err + return + } + errc <- tm.Quit() }() uitest.WaitForGoldenContains(t, drv, errc, diff --git a/truststore/brew.go b/truststore/brew.go index 8be7e49..6fb634d 100644 --- a/truststore/brew.go +++ b/truststore/brew.go @@ -156,7 +156,7 @@ func (s *Brew) UninstallCA(ca *CA) (bool, error) { } if err := s.DataFS.AppendToFile(tmpf, ndata); err != nil { - s.DataFS.Remove(tmpf) + _ = s.DataFS.Remove(tmpf) return false, err } if err := s.DataFS.Rename(tmpf, s.certPath); err != nil { diff --git a/truststore/brew_test.go b/truststore/brew_test.go index 3e1d512..2a2854c 100644 --- a/truststore/brew_test.go +++ b/truststore/brew_test.go @@ -9,7 +9,9 @@ import ( func TestBrew(t *testing.T) { testFS := make(TestFS, 1) - testFS.AppendToFile("cert.pem", nil) + if err := testFS.AppendToFile("cert.pem", nil); err != nil { + t.Fatal(err) + } store := &Brew{ RootDir: "/", diff --git a/truststore/errors.go b/truststore/errors.go index 3260914..f23073d 100644 --- a/truststore/errors.go +++ b/truststore/errors.go @@ -19,10 +19,10 @@ type Op string const ( OpCheck Op = "check" - OpInstall = "install" - OpList = "list" - OpSudo = "sudo" - OpUninstall = "uninstall" + OpInstall Op = "install" + OpList Op = "list" + OpSudo Op = "sudo" + OpUninstall Op = "uninstall" ) type Error struct { diff --git a/truststore/platform_darwin.go b/truststore/platform_darwin.go index 575b0dc..48cf56b 100644 --- a/truststore/platform_darwin.go +++ b/truststore/platform_darwin.go @@ -63,7 +63,6 @@ type Platform struct { SysFS CmdFS inito sync.Once - nssBrowsers string certutilInstallHelp string firefoxProfiles []string } diff --git a/truststore/platform_linux.go b/truststore/platform_linux.go index 666d697..79405e2 100644 --- a/truststore/platform_linux.go +++ b/truststore/platform_linux.go @@ -6,7 +6,7 @@ import ( "encoding/pem" "errors" "fmt" - "io/ioutil" + "os" "path/filepath" "strings" "sync" @@ -22,7 +22,6 @@ type Platform struct { SysFS CmdFS inito sync.Once - nssBrowsers string certutilInstallHelp string trustFilenamePattern string trustCommand []string @@ -114,7 +113,7 @@ func (s *Platform) checkCA(ca *CA) (bool, error) { } func (s *Platform) installCA(ca *CA) (bool, error) { - cert, err := ioutil.ReadFile(ca.FilePath) + cert, err := os.ReadFile(ca.FilePath) if err != nil { return false, fatalErr(err, "failed to read root certificate") } diff --git a/truststore/platform_windows.go b/truststore/platform_windows.go index 1093ba8..0b795b5 100644 --- a/truststore/platform_windows.go +++ b/truststore/platform_windows.go @@ -5,8 +5,8 @@ import ( "encoding/pem" "fmt" "io/fs" - "io/ioutil" "math/big" + "os" "path/filepath" "syscall" "unsafe" @@ -69,7 +69,7 @@ func (s *Platform) checkCA(ca *CA) (bool, error) { func (s *Platform) installCA(ca *CA) (bool, error) { // Load cert - cert, err := ioutil.ReadFile(ca.FilePath) + cert, err := os.ReadFile(ca.FilePath) if err != nil { return false, fatalErr(err, "failed to read root certificate") } diff --git a/ui/styles.go b/ui/styles.go index ff06888..25c394d 100644 --- a/ui/styles.go +++ b/ui/styles.go @@ -15,8 +15,8 @@ var ( header = lipgloss.NewStyle().Bold(true) hint = lipgloss.NewStyle().Faint(true).SetString("|") - Header = header.SetString("#").Render - Skip = header.Faint(true).SetString("# Skipped:").Render + Header = header.SetString("\n#").Render + Skip = header.Faint(true).SetString("\n# Skipped:").Render Hint = hint.Render Underline = lipgloss.NewStyle().Underline(true).Render Warning = header.SetString(bgBanana(fgMidnight("!")) + fgBanana(" Warning:")).Render diff --git a/ui/uitest/uitest.go b/ui/uitest/uitest.go index fdd1e1b..0f02fbb 100644 --- a/ui/uitest/uitest.go +++ b/ui/uitest/uitest.go @@ -113,22 +113,31 @@ var ( waitInterval = 50 * time.Millisecond ) -func WaitForGoldenContains(t *testing.T, drv *ui.Driver, errc chan error, want string) { +func WaitFinished(t *testing.T, drv *ui.Driver, doneCh chan bool) { t.Helper() - if len(errc) > 0 { - t.Fatal(<-errc) + select { + case <-time.After(waitDuration): + t.Fatalf("WaitForFinished: timeout after %s.\n\nGot:\n\n%s", waitDuration, drv.Golden()) + case <-doneCh: } +} + +func WaitForGoldenContains(t *testing.T, drv *ui.Driver, errc chan error, want string) { + t.Helper() start := time.Now() for time.Since(start) <= waitDuration { + if len(errc) > 0 { + t.Fatalf("WaitForGoldenContains error: %v\n\nGot:\n\n%s", <-errc, drv.Golden()) + } if strings.Contains(drv.Golden(), want) { return } time.Sleep(waitInterval) } - t.Fatalf("WaitFor: condition not met after %s.\n\nWant:\n\n%s\n\nGot:\n\n%s", waitDuration, want, drv.Golden()) + t.Fatalf("WaitForGoldenContains: timeout after %s.\n\nWant:\n\n%s\n\nGot:\n\n%s", waitDuration, want, drv.Golden()) } func TestGolden(t *testing.T, got string) { diff --git a/version/version.go b/version/version.go index 5fe90a9..066b3ed 100644 --- a/version/version.go +++ b/version/version.go @@ -70,7 +70,11 @@ func MinimumVersionCheck(minimumVersion string) error { Model: ui.Section{ Name: "MinimumVersionCheck", Model: ui.MessageLines{ - ui.Danger(fmt.Sprintf("This version of the Anchor CLI is out-of-date, please update.")), + ui.Header( + fmt.Sprintf("%s This version of the Anchor CLI is out-of-date, please update.", + ui.Danger("Error!"), + ), + ), }, }, }