Skip to content

Commit 779c446

Browse files
authored
cli prints license warnings (#3716)
* cli prints license warnings Signed-off-by: Spike Curtis <spike@coder.com> * Satisfy the linter Signed-off-by: Spike Curtis <spike@coder.com> Signed-off-by: Spike Curtis <spike@coder.com>
1 parent 62f686c commit 779c446

File tree

2 files changed

+69
-35
lines changed

2 files changed

+69
-35
lines changed

cli/root.go

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,20 @@ var (
3535
)
3636

3737
const (
38-
varURL = "url"
39-
varToken = "token"
40-
varAgentToken = "agent-token"
41-
varAgentURL = "agent-url"
42-
varGlobalConfig = "global-config"
43-
varNoOpen = "no-open"
44-
varNoVersionCheck = "no-version-warning"
45-
varForceTty = "force-tty"
46-
varVerbose = "verbose"
47-
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
48-
49-
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
38+
varURL = "url"
39+
varToken = "token"
40+
varAgentToken = "agent-token"
41+
varAgentURL = "agent-url"
42+
varGlobalConfig = "global-config"
43+
varNoOpen = "no-open"
44+
varNoVersionCheck = "no-version-warning"
45+
varNoFeatureWarning = "no-feature-warning"
46+
varForceTty = "force-tty"
47+
varVerbose = "verbose"
48+
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
49+
50+
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
51+
envNoFeatureWarning = "CODER_NO_FEATURE_WARNING"
5052
)
5153

5254
var (
@@ -103,36 +105,33 @@ func Root(subcommands []*cobra.Command) *cobra.Command {
103105
Long: `Coder — A tool for provisioning self-hosted development environments.
104106
`,
105107
PersistentPreRun: func(cmd *cobra.Command, args []string) {
106-
err := func() error {
107-
if cliflag.IsSetBool(cmd, varNoVersionCheck) {
108-
return nil
109-
}
110-
111-
// Login handles checking the versions itself since it
112-
// has a handle to an unauthenticated client.
113-
// Server is skipped for obvious reasons.
114-
if cmd.Name() == "login" || cmd.Name() == "server" || cmd.Name() == "gitssh" {
115-
return nil
116-
}
117-
118-
client, err := CreateClient(cmd)
119-
// If the client is unauthenticated we can ignore the check.
120-
// The child commands should handle an unauthenticated client.
121-
if xerrors.Is(err, errUnauthenticated) {
122-
return nil
123-
}
124-
if err != nil {
125-
return xerrors.Errorf("create client: %w", err)
126-
}
127-
return checkVersions(cmd, client)
128-
}()
108+
if cliflag.IsSetBool(cmd, varNoVersionCheck) &&
109+
cliflag.IsSetBool(cmd, varNoFeatureWarning) {
110+
return
111+
}
112+
113+
// Login handles checking the versions itself since it
114+
// has a handle to an unauthenticated client.
115+
// Server is skipped for obvious reasons.
116+
if cmd.Name() == "login" || cmd.Name() == "server" || cmd.Name() == "gitssh" {
117+
return
118+
}
119+
120+
client, err := CreateClient(cmd)
121+
// If we are unable to create a client, presumably the subcommand will fail as well
122+
// so we can bail out here.
123+
if err != nil {
124+
return
125+
}
126+
err = checkVersions(cmd, client)
129127
if err != nil {
130128
// Just log the error here. We never want to fail a command
131129
// due to a pre-run.
132130
_, _ = fmt.Fprintf(cmd.ErrOrStderr(),
133131
cliui.Styles.Warn.Render("check versions error: %s"), err)
134132
_, _ = fmt.Fprintln(cmd.ErrOrStderr())
135133
}
134+
checkWarnings(cmd, client)
136135
},
137136
Example: formatExamples(
138137
example{
@@ -152,6 +151,7 @@ func Root(subcommands []*cobra.Command) *cobra.Command {
152151

153152
cmd.PersistentFlags().String(varURL, "", "Specify the URL to your deployment.")
154153
cliflag.Bool(cmd.PersistentFlags(), varNoVersionCheck, "", envNoVersionCheck, false, "Suppress warning when client and server versions do not match.")
154+
cliflag.Bool(cmd.PersistentFlags(), varNoFeatureWarning, "", envNoFeatureWarning, false, "Suppress warnings about unlicensed features.")
155155
cliflag.String(cmd.PersistentFlags(), varToken, "", envSessionToken, "", fmt.Sprintf("Specify an authentication token. For security reasons setting %s is preferred.", envSessionToken))
156156
cliflag.String(cmd.PersistentFlags(), varAgentToken, "", "CODER_AGENT_TOKEN", "", "Specify an agent authentication token.")
157157
_ = cmd.PersistentFlags().MarkHidden(varAgentToken)
@@ -493,3 +493,16 @@ download the server version with: 'curl -L https://coder.com/install.sh | sh -s
493493

494494
return nil
495495
}
496+
497+
func checkWarnings(cmd *cobra.Command, client *codersdk.Client) {
498+
if cliflag.IsSetBool(cmd, varNoFeatureWarning) {
499+
return
500+
}
501+
entitlements, err := client.Entitlements(cmd.Context())
502+
if err != nil {
503+
return
504+
}
505+
for _, w := range entitlements.Warnings {
506+
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), cliui.Styles.Warn.Render(w))
507+
}
508+
}

enterprise/cli/licenses_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/coder/coder/cli/clitest"
2222
"github.com/coder/coder/coderd/coderdtest"
23+
"github.com/coder/coder/coderd/httpapi"
2324
"github.com/coder/coder/codersdk"
2425
"github.com/coder/coder/enterprise/cli"
2526
"github.com/coder/coder/enterprise/coderd"
@@ -28,6 +29,7 @@ import (
2829
)
2930

3031
const fakeLicenseJWT = "test.jwt.sig"
32+
const testWarning = "This is a test warning"
3133

3234
func TestLicensesAddFake(t *testing.T) {
3335
t.Parallel()
@@ -179,6 +181,8 @@ func TestLicensesListReal(t *testing.T) {
179181
"licenses", "list")
180182
stdout := new(bytes.Buffer)
181183
cmd.SetOut(stdout)
184+
stderr := new(bytes.Buffer)
185+
cmd.SetErr(stderr)
182186
clitest.SetupConfig(t, client, root)
183187
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
184188
defer cancel()
@@ -188,6 +192,7 @@ func TestLicensesListReal(t *testing.T) {
188192
}()
189193
require.NoError(t, <-errC)
190194
assert.Equal(t, "[]\n", stdout.String())
195+
assert.Contains(t, testWarning, stderr.String())
191196
})
192197
}
193198

@@ -260,6 +265,7 @@ func newFakeLicenseAPI(t *testing.T) http.Handler {
260265
r.Get("/api/v2/licenses", a.licenses)
261266
r.Get("/api/v2/buildinfo", a.noop)
262267
r.Delete("/api/v2/licenses/{id}", a.deleteLicense)
268+
r.Get("/api/v2/entitlements", a.entitlements)
263269
return r
264270
}
265271

@@ -330,3 +336,18 @@ func (s *fakeLicenseAPI) deleteLicense(rw http.ResponseWriter, r *http.Request)
330336
assert.Equal(s.t, "55", chi.URLParam(r, "id"))
331337
rw.WriteHeader(200)
332338
}
339+
340+
func (*fakeLicenseAPI) entitlements(rw http.ResponseWriter, _ *http.Request) {
341+
features := make(map[string]codersdk.Feature)
342+
for _, f := range codersdk.FeatureNames {
343+
features[f] = codersdk.Feature{
344+
Entitlement: codersdk.EntitlementEntitled,
345+
Enabled: true,
346+
}
347+
}
348+
httpapi.Write(rw, http.StatusOK, codersdk.Entitlements{
349+
Features: features,
350+
Warnings: []string{testWarning},
351+
HasLicense: true,
352+
})
353+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy