feat: add experimental flag (#4364)

This commit is contained in:
Garrett Delfosse
2022-10-04 15:45:00 -04:00
committed by GitHub
parent 18b282cabb
commit ffbaa93722
12 changed files with 55 additions and 9 deletions
+18
View File
@@ -48,10 +48,12 @@ const (
varNoFeatureWarning = "no-feature-warning"
varForceTty = "force-tty"
varVerbose = "verbose"
varExperimental = "experimental"
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
envNoFeatureWarning = "CODER_NO_FEATURE_WARNING"
envExperimental = "CODER_EXPERIMENTAL"
)
var (
@@ -184,6 +186,7 @@ func Root(subcommands []*cobra.Command) *cobra.Command {
cmd.PersistentFlags().Bool(varNoOpen, false, "Block automatically opening URLs in the browser.")
_ = cmd.PersistentFlags().MarkHidden(varNoOpen)
cliflag.Bool(cmd.PersistentFlags(), varVerbose, "v", "CODER_VERBOSE", false, "Enable verbose output.")
cliflag.Bool(cmd.PersistentFlags(), varExperimental, "", envExperimental, false, "Enable experimental features. Experimental features are not ready for production.")
return cmd
}
@@ -598,3 +601,18 @@ func (h *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) {
}
return h.transport.RoundTrip(req)
}
// ExperimentalEnabled returns if the experimental feature flag is enabled.
func ExperimentalEnabled(cmd *cobra.Command) bool {
return cliflag.IsSetBool(cmd, varExperimental)
}
// EnsureExperimental will ensure that the experimental feature flag is set if the given flag is set.
func EnsureExperimental(cmd *cobra.Command, name string) error {
_, set := cliflag.IsSet(cmd, name)
if set && !ExperimentalEnabled(cmd) {
return xerrors.Errorf("flag %s is set but requires flag --experimental or environment variable CODER_EXPERIMENTAL=true.", name)
}
return nil
}
+16
View File
@@ -13,6 +13,7 @@ import (
"github.com/coder/coder/buildinfo"
"github.com/coder/coder/cli"
"github.com/coder/coder/cli/cliflag"
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/codersdk"
)
@@ -153,4 +154,19 @@ func TestRoot(t *testing.T) {
// This won't succeed, because we're using the login cmd to assert requests.
_ = cmd.Execute()
})
t.Run("Experimental", func(t *testing.T) {
t.Parallel()
cmd, _ := clitest.New(t, "--experimental")
err := cmd.Execute()
require.NoError(t, err)
require.True(t, cli.ExperimentalEnabled(cmd))
cmd, _ = clitest.New(t, "help", "--verbose")
_ = cmd.Execute()
_, set := cliflag.IsSet(cmd, "verbose")
require.True(t, set)
require.ErrorContains(t, cli.EnsureExperimental(cmd, "verbose"), "--experimental")
})
}
+1
View File
@@ -368,6 +368,7 @@ func Server(newAPI func(context.Context, *coderd.Options) (*coderd.API, error))
AutoImportTemplates: validatedAutoImportTemplates,
MetricsCacheRefreshInterval: metricsCacheRefreshInterval,
AgentStatsRefreshInterval: agentStatRefreshInterval,
Experimental: ExperimentalEnabled(cmd),
}
if oauth2GithubClientSecret != "" {
+1
View File
@@ -81,6 +81,7 @@ type Options struct {
MetricsCacheRefreshInterval time.Duration
AgentStatsRefreshInterval time.Duration
Experimental bool
}
// New constructs a Coder API handler.
+4 -3
View File
@@ -38,9 +38,10 @@ type Feature struct {
}
type Entitlements struct {
Features map[string]Feature `json:"features"`
Warnings []string `json:"warnings"`
HasLicense bool `json:"has_license"`
Features map[string]Feature `json:"features"`
Warnings []string `json:"warnings"`
HasLicense bool `json:"has_license"`
Experimental bool `json:"experimental"`
}
func (c *Client) Entitlements(ctx context.Context) (Entitlements, error) {
+1
View File
@@ -68,5 +68,6 @@ func TestFeaturesList(t *testing.T) {
assert.Equal(t, codersdk.EntitlementNotEntitled,
entitlements.Features[codersdk.FeatureWorkspaceQuota].Entitlement)
assert.False(t, entitlements.HasLicense)
assert.False(t, entitlements.Experimental)
})
}
+4 -3
View File
@@ -346,8 +346,9 @@ func (*fakeLicenseAPI) entitlements(rw http.ResponseWriter, r *http.Request) {
}
}
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.Entitlements{
Features: features,
Warnings: []string{testWarning},
HasLicense: true,
Features: features,
Warnings: []string{testWarning},
HasLicense: true,
Experimental: true,
})
}
+4 -3
View File
@@ -237,9 +237,10 @@ func (api *API) serveEntitlements(rw http.ResponseWriter, r *http.Request) {
api.entitlementsMu.RUnlock()
resp := codersdk.Entitlements{
Features: make(map[string]codersdk.Feature),
Warnings: make([]string, 0),
HasLicense: entitlements.hasLicense,
Features: make(map[string]codersdk.Feature),
Warnings: make([]string, 0),
HasLicense: entitlements.hasLicense,
Experimental: api.Experimental,
}
if entitlements.activeUsers.Limit != nil {
+1
View File
@@ -29,6 +29,7 @@ export const defaultEntitlements = (): TypesGen.Entitlements => {
features: features,
has_license: false,
warnings: [],
experimental: false,
}
}
+1
View File
@@ -244,6 +244,7 @@ export interface Entitlements {
readonly features: Record<string, Feature>
readonly warnings: string[]
readonly has_license: boolean
readonly experimental: boolean
}
// From codersdk/features.go
+3
View File
@@ -771,11 +771,13 @@ export const MockEntitlements: TypesGen.Entitlements = {
warnings: [],
has_license: false,
features: {},
experimental: false,
}
export const MockEntitlementsWithWarnings: TypesGen.Entitlements = {
warnings: ["You are over your active user limit.", "And another thing."],
has_license: true,
experimental: false,
features: {
user_limit: {
enabled: true,
@@ -797,6 +799,7 @@ export const MockEntitlementsWithWarnings: TypesGen.Entitlements = {
export const MockEntitlementsWithAuditLog: TypesGen.Entitlements = {
warnings: [],
has_license: true,
experimental: false,
features: {
audit_log: {
enabled: true,
@@ -23,6 +23,7 @@ const emptyEntitlements = {
warnings: [],
features: {},
has_license: false,
experimental: false,
}
export const entitlementsMachine = createMachine(