mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: add support for telemetry-required licenses (#6194)
This commit is contained in:
3
coderd/apidoc/docs.go
generated
3
coderd/apidoc/docs.go
generated
@ -6422,6 +6422,9 @@ const docTemplate = `{
|
|||||||
"has_license": {
|
"has_license": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"require_telemetry": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"trial": {
|
"trial": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
3
coderd/apidoc/swagger.json
generated
3
coderd/apidoc/swagger.json
generated
@ -5742,6 +5742,9 @@
|
|||||||
"has_license": {
|
"has_license": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"require_telemetry": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"trial": {
|
"trial": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@ -81,11 +81,12 @@ type Feature struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Entitlements struct {
|
type Entitlements struct {
|
||||||
Features map[FeatureName]Feature `json:"features"`
|
Features map[FeatureName]Feature `json:"features"`
|
||||||
Warnings []string `json:"warnings"`
|
Warnings []string `json:"warnings"`
|
||||||
Errors []string `json:"errors"`
|
Errors []string `json:"errors"`
|
||||||
HasLicense bool `json:"has_license"`
|
HasLicense bool `json:"has_license"`
|
||||||
Trial bool `json:"trial"`
|
Trial bool `json:"trial"`
|
||||||
|
RequireTelemetry bool `json:"require_telemetry"`
|
||||||
|
|
||||||
// DEPRECATED: use Experiments instead.
|
// DEPRECATED: use Experiments instead.
|
||||||
Experimental bool `json:"experimental"`
|
Experimental bool `json:"experimental"`
|
||||||
|
@ -128,6 +128,7 @@ curl -X GET http://coder-server:8080/api/v2/entitlements \
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"has_license": true,
|
"has_license": true,
|
||||||
|
"require_telemetry": true,
|
||||||
"trial": true,
|
"trial": true,
|
||||||
"warnings": ["string"]
|
"warnings": ["string"]
|
||||||
}
|
}
|
||||||
|
@ -2806,6 +2806,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"has_license": true,
|
"has_license": true,
|
||||||
|
"require_telemetry": true,
|
||||||
"trial": true,
|
"trial": true,
|
||||||
"warnings": ["string"]
|
"warnings": ["string"]
|
||||||
}
|
}
|
||||||
@ -2813,15 +2814,16 @@ CreateParameterRequest is a structure used to create a new parameter value for a
|
|||||||
|
|
||||||
### Properties
|
### Properties
|
||||||
|
|
||||||
| Name | Type | Required | Restrictions | Description |
|
| Name | Type | Required | Restrictions | Description |
|
||||||
| ------------------ | ------------------------------------ | -------- | ------------ | ------------------------------------- |
|
| ------------------- | ------------------------------------ | -------- | ------------ | ------------------------------------- |
|
||||||
| `errors` | array of string | false | | |
|
| `errors` | array of string | false | | |
|
||||||
| `experimental` | boolean | false | | Experimental use Experiments instead. |
|
| `experimental` | boolean | false | | Experimental use Experiments instead. |
|
||||||
| `features` | object | false | | |
|
| `features` | object | false | | |
|
||||||
| » `[any property]` | [codersdk.Feature](#codersdkfeature) | false | | |
|
| » `[any property]` | [codersdk.Feature](#codersdkfeature) | false | | |
|
||||||
| `has_license` | boolean | false | | |
|
| `has_license` | boolean | false | | |
|
||||||
| `trial` | boolean | false | | |
|
| `require_telemetry` | boolean | false | | |
|
||||||
| `warnings` | array of string | false | | |
|
| `trial` | boolean | false | | |
|
||||||
|
| `warnings` | array of string | false | | |
|
||||||
|
|
||||||
## codersdk.Experiment
|
## codersdk.Experiment
|
||||||
|
|
||||||
|
@ -254,6 +254,17 @@ func (api *API) updateEntitlements(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if entitlements.RequireTelemetry && !api.DeploymentConfig.Telemetry.Enable.Value {
|
||||||
|
// We can't fail because then the user couldn't remove the offending
|
||||||
|
// license w/o a restart.
|
||||||
|
api.entitlements.Errors = []string{
|
||||||
|
"License requires telemetry but telemetry is disabled",
|
||||||
|
}
|
||||||
|
api.Logger.Error(ctx, "license requires telemetry enabled")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
entitlements.Experimental = api.DeploymentConfig.Experimental.Value || len(api.AGPL.Experiments) != 0
|
entitlements.Experimental = api.DeploymentConfig.Experimental.Value || len(api.AGPL.Experiments) != 0
|
||||||
|
|
||||||
featureChanged := func(featureName codersdk.FeatureName) (changed bool, enabled bool) {
|
featureChanged := func(featureName codersdk.FeatureName) (changed bool, enabled bool) {
|
||||||
|
@ -98,6 +98,7 @@ func Entitlements(
|
|||||||
if claims.AllFeatures {
|
if claims.AllFeatures {
|
||||||
allFeatures = true
|
allFeatures = true
|
||||||
}
|
}
|
||||||
|
entitlements.RequireTelemetry = entitlements.RequireTelemetry || claims.RequireTelemetry
|
||||||
}
|
}
|
||||||
|
|
||||||
if allFeatures {
|
if allFeatures {
|
||||||
@ -224,13 +225,14 @@ type Claims struct {
|
|||||||
// the end of the grace period (identical to LicenseExpires if there is no grace period).
|
// the end of the grace period (identical to LicenseExpires if there is no grace period).
|
||||||
// The reason we use the standard claim for the end of the grace period is that we want JWT
|
// The reason we use the standard claim for the end of the grace period is that we want JWT
|
||||||
// processing libraries to consider the token "valid" until then.
|
// processing libraries to consider the token "valid" until then.
|
||||||
LicenseExpires *jwt.NumericDate `json:"license_expires,omitempty"`
|
LicenseExpires *jwt.NumericDate `json:"license_expires,omitempty"`
|
||||||
AccountType string `json:"account_type,omitempty"`
|
AccountType string `json:"account_type,omitempty"`
|
||||||
AccountID string `json:"account_id,omitempty"`
|
AccountID string `json:"account_id,omitempty"`
|
||||||
Trial bool `json:"trial"`
|
Trial bool `json:"trial"`
|
||||||
AllFeatures bool `json:"all_features"`
|
AllFeatures bool `json:"all_features"`
|
||||||
Version uint64 `json:"version"`
|
Version uint64 `json:"version"`
|
||||||
Features Features `json:"features"`
|
Features Features `json:"features"`
|
||||||
|
RequireTelemetry bool `json:"require_telemetry,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseRaw consumes a license and returns the claims.
|
// ParseRaw consumes a license and returns the claims.
|
||||||
|
@ -654,6 +654,7 @@ export const getEntitlements = async (): Promise<TypesGen.Entitlements> => {
|
|||||||
experimental: false,
|
experimental: false,
|
||||||
features: withDefaultFeatures({}),
|
features: withDefaultFeatures({}),
|
||||||
has_license: false,
|
has_license: false,
|
||||||
|
require_telemetry: false,
|
||||||
trial: false,
|
trial: false,
|
||||||
warnings: [],
|
warnings: [],
|
||||||
}
|
}
|
||||||
|
@ -359,6 +359,7 @@ export interface Entitlements {
|
|||||||
readonly errors: string[]
|
readonly errors: string[]
|
||||||
readonly has_license: boolean
|
readonly has_license: boolean
|
||||||
readonly trial: boolean
|
readonly trial: boolean
|
||||||
|
readonly require_telemetry: boolean
|
||||||
readonly experimental: boolean
|
readonly experimental: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,6 +1119,7 @@ export const MockEntitlements: TypesGen.Entitlements = {
|
|||||||
has_license: false,
|
has_license: false,
|
||||||
features: withDefaultFeatures({}),
|
features: withDefaultFeatures({}),
|
||||||
experimental: false,
|
experimental: false,
|
||||||
|
require_telemetry: false,
|
||||||
trial: false,
|
trial: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,6 +1129,7 @@ export const MockEntitlementsWithWarnings: TypesGen.Entitlements = {
|
|||||||
has_license: true,
|
has_license: true,
|
||||||
experimental: false,
|
experimental: false,
|
||||||
trial: false,
|
trial: false,
|
||||||
|
require_telemetry: false,
|
||||||
features: withDefaultFeatures({
|
features: withDefaultFeatures({
|
||||||
user_limit: {
|
user_limit: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
@ -1151,6 +1153,7 @@ export const MockEntitlementsWithAuditLog: TypesGen.Entitlements = {
|
|||||||
warnings: [],
|
warnings: [],
|
||||||
has_license: true,
|
has_license: true,
|
||||||
experimental: false,
|
experimental: false,
|
||||||
|
require_telemetry: false,
|
||||||
trial: false,
|
trial: false,
|
||||||
features: withDefaultFeatures({
|
features: withDefaultFeatures({
|
||||||
audit_log: {
|
audit_log: {
|
||||||
|
Reference in New Issue
Block a user