mirror of https://github.com/coder/coder.git
feat(coderd): expose parameter description and type (#8944)
This commit is contained in:
parent
00be8ab875
commit
e8627195a2
|
@ -9585,6 +9585,9 @@ const docTemplate = `{
|
|||
"codersdk.TemplateParameterUsage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -9604,6 +9607,9 @@ const docTemplate = `{
|
|||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
|
@ -8665,6 +8665,9 @@
|
|||
"codersdk.TemplateParameterUsage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -8684,6 +8687,9 @@
|
|||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
|
@ -3,6 +3,7 @@ package db2sdk
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sort"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
|
@ -29,20 +30,10 @@ func WorkspaceBuildParameter(p database.WorkspaceBuildParameter) codersdk.Worksp
|
|||
}
|
||||
|
||||
func TemplateVersionParameter(param database.TemplateVersionParameter) (codersdk.TemplateVersionParameter, error) {
|
||||
var protoOptions []*proto.RichParameterOption
|
||||
err := json.Unmarshal(param.Options, &protoOptions)
|
||||
options, err := templateVersionParameterOptions(param.Options)
|
||||
if err != nil {
|
||||
return codersdk.TemplateVersionParameter{}, err
|
||||
}
|
||||
options := make([]codersdk.TemplateVersionParameterOption, 0)
|
||||
for _, option := range protoOptions {
|
||||
options = append(options, codersdk.TemplateVersionParameterOption{
|
||||
Name: option.Name,
|
||||
Description: option.Description,
|
||||
Value: option.Value,
|
||||
Icon: option.Icon,
|
||||
})
|
||||
}
|
||||
|
||||
descriptionPlaintext, err := parameter.Plaintext(param.Description)
|
||||
if err != nil {
|
||||
|
@ -132,3 +123,61 @@ func Role(role rbac.Role) codersdk.Role {
|
|||
Name: role.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func TemplateInsightsParameters(parameterRows []database.GetTemplateParameterInsightsRow) ([]codersdk.TemplateParameterUsage, error) {
|
||||
parametersByNum := make(map[int64]*codersdk.TemplateParameterUsage)
|
||||
for _, param := range parameterRows {
|
||||
if _, ok := parametersByNum[param.Num]; !ok {
|
||||
var opts []codersdk.TemplateVersionParameterOption
|
||||
err := json.Unmarshal(param.Options, &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
plaintextDescription, err := parameter.Plaintext(param.Description)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parametersByNum[param.Num] = &codersdk.TemplateParameterUsage{
|
||||
TemplateIDs: param.TemplateIDs,
|
||||
Name: param.Name,
|
||||
Type: param.Type,
|
||||
DisplayName: param.DisplayName,
|
||||
Description: plaintextDescription,
|
||||
Options: opts,
|
||||
}
|
||||
}
|
||||
parametersByNum[param.Num].Values = append(parametersByNum[param.Num].Values, codersdk.TemplateParameterValue{
|
||||
Value: param.Value,
|
||||
Count: param.Count,
|
||||
})
|
||||
}
|
||||
parametersUsage := []codersdk.TemplateParameterUsage{}
|
||||
for _, param := range parametersByNum {
|
||||
parametersUsage = append(parametersUsage, *param)
|
||||
}
|
||||
|
||||
sort.Slice(parametersUsage, func(i, j int) bool {
|
||||
return parametersUsage[i].Name < parametersUsage[j].Name
|
||||
})
|
||||
return parametersUsage, nil
|
||||
}
|
||||
|
||||
func templateVersionParameterOptions(rawOptions json.RawMessage) ([]codersdk.TemplateVersionParameterOption, error) {
|
||||
var protoOptions []*proto.RichParameterOption
|
||||
err := json.Unmarshal(rawOptions, &protoOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var options []codersdk.TemplateVersionParameterOption
|
||||
for _, option := range protoOptions {
|
||||
options = append(options, codersdk.TemplateVersionParameterOption{
|
||||
Name: option.Name,
|
||||
Description: option.Description,
|
||||
Value: option.Value,
|
||||
Icon: option.Icon,
|
||||
})
|
||||
}
|
||||
return options, nil
|
||||
}
|
||||
|
|
|
@ -2186,6 +2186,7 @@ func (q *FakeQuerier) GetTemplateParameterInsights(ctx context.Context, arg data
|
|||
uniqueTemplateParams[key] = &database.GetTemplateParameterInsightsRow{
|
||||
Num: num,
|
||||
Name: tvp.Name,
|
||||
Type: tvp.Type,
|
||||
DisplayName: tvp.DisplayName,
|
||||
Description: tvp.Description,
|
||||
Options: tvp.Options,
|
||||
|
@ -2220,6 +2221,7 @@ func (q *FakeQuerier) GetTemplateParameterInsights(ctx context.Context, arg data
|
|||
TemplateIDs: uniqueSortedUUIDs(utp.TemplateIDs),
|
||||
Name: utp.Name,
|
||||
DisplayName: utp.DisplayName,
|
||||
Type: utp.Type,
|
||||
Description: utp.Description,
|
||||
Options: utp.Options,
|
||||
Value: value,
|
||||
|
|
|
@ -1582,16 +1582,18 @@ WITH latest_workspace_builds AS (
|
|||
tvp.name,
|
||||
tvp.display_name,
|
||||
tvp.description,
|
||||
tvp.options
|
||||
tvp.options,
|
||||
tvp.type
|
||||
FROM latest_workspace_builds wb
|
||||
JOIN template_version_parameters tvp ON (tvp.template_version_id = wb.template_version_id)
|
||||
GROUP BY tvp.name, tvp.display_name, tvp.description, tvp.options
|
||||
GROUP BY tvp.name, tvp.display_name, tvp.description, tvp.options, tvp.type
|
||||
)
|
||||
|
||||
SELECT
|
||||
utp.num,
|
||||
utp.template_ids,
|
||||
utp.name,
|
||||
utp.type,
|
||||
utp.display_name,
|
||||
utp.description,
|
||||
utp.options,
|
||||
|
@ -1599,7 +1601,7 @@ SELECT
|
|||
COUNT(wbp.value) AS count
|
||||
FROM unique_template_params utp
|
||||
JOIN workspace_build_parameters wbp ON (utp.workspace_build_ids @> ARRAY[wbp.workspace_build_id] AND utp.name = wbp.name)
|
||||
GROUP BY utp.num, utp.name, utp.display_name, utp.description, utp.options, utp.template_ids, wbp.value
|
||||
GROUP BY utp.num, utp.name, utp.display_name, utp.description, utp.options, utp.template_ids, utp.type, wbp.value
|
||||
`
|
||||
|
||||
type GetTemplateParameterInsightsParams struct {
|
||||
|
@ -1612,6 +1614,7 @@ type GetTemplateParameterInsightsRow struct {
|
|||
Num int64 `db:"num" json:"num"`
|
||||
TemplateIDs []uuid.UUID `db:"template_ids" json:"template_ids"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Type string `db:"type" json:"type"`
|
||||
DisplayName string `db:"display_name" json:"display_name"`
|
||||
Description string `db:"description" json:"description"`
|
||||
Options json.RawMessage `db:"options" json:"options"`
|
||||
|
@ -1636,6 +1639,7 @@ func (q *sqlQuerier) GetTemplateParameterInsights(ctx context.Context, arg GetTe
|
|||
&i.Num,
|
||||
pq.Array(&i.TemplateIDs),
|
||||
&i.Name,
|
||||
&i.Type,
|
||||
&i.DisplayName,
|
||||
&i.Description,
|
||||
&i.Options,
|
||||
|
|
|
@ -149,16 +149,18 @@ WITH latest_workspace_builds AS (
|
|||
tvp.name,
|
||||
tvp.display_name,
|
||||
tvp.description,
|
||||
tvp.options
|
||||
tvp.options,
|
||||
tvp.type
|
||||
FROM latest_workspace_builds wb
|
||||
JOIN template_version_parameters tvp ON (tvp.template_version_id = wb.template_version_id)
|
||||
GROUP BY tvp.name, tvp.display_name, tvp.description, tvp.options
|
||||
GROUP BY tvp.name, tvp.display_name, tvp.description, tvp.options, tvp.type
|
||||
)
|
||||
|
||||
SELECT
|
||||
utp.num,
|
||||
utp.template_ids,
|
||||
utp.name,
|
||||
utp.type,
|
||||
utp.display_name,
|
||||
utp.description,
|
||||
utp.options,
|
||||
|
@ -166,4 +168,4 @@ SELECT
|
|||
COUNT(wbp.value) AS count
|
||||
FROM unique_template_params utp
|
||||
JOIN workspace_build_parameters wbp ON (utp.workspace_build_ids @> ARRAY[wbp.workspace_build_id] AND utp.name = wbp.name)
|
||||
GROUP BY utp.num, utp.name, utp.display_name, utp.description, utp.options, utp.template_ids, wbp.value;
|
||||
GROUP BY utp.num, utp.name, utp.display_name, utp.description, utp.options, utp.template_ids, utp.type, wbp.value;
|
||||
|
|
|
@ -2,10 +2,8 @@ package coderd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
@ -13,6 +11,7 @@ import (
|
|||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/database/db2sdk"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
"github.com/coder/coder/coderd/rbac"
|
||||
"github.com/coder/coder/codersdk"
|
||||
|
@ -244,7 +243,7 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
parametersUsage, err := convertTemplateInsightsParameters(parameterRows)
|
||||
parametersUsage, err := db2sdk.TemplateInsightsParameters(parameterRows)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error converting template parameter insights.",
|
||||
|
@ -315,39 +314,6 @@ func convertTemplateInsightsBuiltinApps(usage database.GetTemplateInsightsRow) [
|
|||
}
|
||||
}
|
||||
|
||||
func convertTemplateInsightsParameters(parameterRows []database.GetTemplateParameterInsightsRow) ([]codersdk.TemplateParameterUsage, error) {
|
||||
parametersByNum := make(map[int64]*codersdk.TemplateParameterUsage)
|
||||
for _, param := range parameterRows {
|
||||
if _, ok := parametersByNum[param.Num]; !ok {
|
||||
var opts []codersdk.TemplateVersionParameterOption
|
||||
err := json.Unmarshal(param.Options, &opts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unmarshal template parameter options: %w", err)
|
||||
}
|
||||
parametersByNum[param.Num] = &codersdk.TemplateParameterUsage{
|
||||
TemplateIDs: param.TemplateIDs,
|
||||
Name: param.Name,
|
||||
DisplayName: param.DisplayName,
|
||||
Options: opts,
|
||||
}
|
||||
}
|
||||
parametersByNum[param.Num].Values = append(parametersByNum[param.Num].Values, codersdk.TemplateParameterValue{
|
||||
Value: param.Value,
|
||||
Count: param.Count,
|
||||
})
|
||||
}
|
||||
parametersUsage := []codersdk.TemplateParameterUsage{}
|
||||
for _, param := range parametersByNum {
|
||||
parametersUsage = append(parametersUsage, *param)
|
||||
}
|
||||
|
||||
sort.Slice(parametersUsage, func(i, j int) bool {
|
||||
return parametersUsage[i].Name < parametersUsage[j].Name
|
||||
})
|
||||
|
||||
return parametersUsage, nil
|
||||
}
|
||||
|
||||
// parseInsightsStartAndEndTime parses the start and end time query parameters
|
||||
// and returns the parsed values. The client provided timezone must be preserved
|
||||
// when parsing the time. Verification is performed so that the start and end
|
||||
|
|
|
@ -405,6 +405,8 @@ func TestTemplateInsights(t *testing.T) {
|
|||
// The workspace uses 3 parameters
|
||||
require.Len(t, resp.Report.ParametersUsage, 3)
|
||||
assert.Equal(t, firstParameterName, resp.Report.ParametersUsage[0].Name)
|
||||
assert.Equal(t, firstParameterType, resp.Report.ParametersUsage[0].Type)
|
||||
assert.Equal(t, firstParameterDescription, resp.Report.ParametersUsage[0].Description)
|
||||
assert.Equal(t, firstParameterDisplayName, resp.Report.ParametersUsage[0].DisplayName)
|
||||
assert.Contains(t, resp.Report.ParametersUsage[0].Values, codersdk.TemplateParameterValue{
|
||||
Value: firstParameterValue,
|
||||
|
@ -414,6 +416,8 @@ func TestTemplateInsights(t *testing.T) {
|
|||
assert.Empty(t, resp.Report.ParametersUsage[0].Options)
|
||||
|
||||
assert.Equal(t, secondParameterName, resp.Report.ParametersUsage[1].Name)
|
||||
assert.Equal(t, secondParameterType, resp.Report.ParametersUsage[1].Type)
|
||||
assert.Equal(t, secondParameterDescription, resp.Report.ParametersUsage[1].Description)
|
||||
assert.Equal(t, secondParameterDisplayName, resp.Report.ParametersUsage[1].DisplayName)
|
||||
assert.Contains(t, resp.Report.ParametersUsage[1].Values, codersdk.TemplateParameterValue{
|
||||
Value: secondParameterValue,
|
||||
|
@ -423,6 +427,8 @@ func TestTemplateInsights(t *testing.T) {
|
|||
assert.Empty(t, resp.Report.ParametersUsage[1].Options)
|
||||
|
||||
assert.Equal(t, thirdParameterName, resp.Report.ParametersUsage[2].Name)
|
||||
assert.Equal(t, thirdParameterType, resp.Report.ParametersUsage[2].Type)
|
||||
assert.Equal(t, thirdParameterDescription, resp.Report.ParametersUsage[2].Description)
|
||||
assert.Equal(t, thirdParameterDisplayName, resp.Report.ParametersUsage[2].DisplayName)
|
||||
assert.Contains(t, resp.Report.ParametersUsage[2].Values, codersdk.TemplateParameterValue{
|
||||
Value: thirdParameterValue,
|
||||
|
|
|
@ -138,6 +138,8 @@ type TemplateParameterUsage struct {
|
|||
TemplateIDs []uuid.UUID `json:"template_ids" format:"uuid"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Description string `json:"description"`
|
||||
Options []TemplateVersionParameterOption `json:"options,omitempty"`
|
||||
Values []TemplateParameterValue `json:"values"`
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ curl -X GET http://coder-server:8080/api/v2/insights/templates \
|
|||
"end_time": "2019-08-24T14:15:22Z",
|
||||
"parameters_usage": [
|
||||
{
|
||||
"description": "string",
|
||||
"display_name": "string",
|
||||
"name": "string",
|
||||
"options": [
|
||||
|
@ -91,6 +92,7 @@ curl -X GET http://coder-server:8080/api/v2/insights/templates \
|
|||
}
|
||||
],
|
||||
"template_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
|
||||
"type": "string",
|
||||
"values": [
|
||||
{
|
||||
"count": 0,
|
||||
|
|
|
@ -4321,6 +4321,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
"end_time": "2019-08-24T14:15:22Z",
|
||||
"parameters_usage": [
|
||||
{
|
||||
"description": "string",
|
||||
"display_name": "string",
|
||||
"name": "string",
|
||||
"options": [
|
||||
|
@ -4332,6 +4333,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
}
|
||||
],
|
||||
"template_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
|
||||
"type": "string",
|
||||
"values": [
|
||||
{
|
||||
"count": 0,
|
||||
|
@ -4384,6 +4386,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
"end_time": "2019-08-24T14:15:22Z",
|
||||
"parameters_usage": [
|
||||
{
|
||||
"description": "string",
|
||||
"display_name": "string",
|
||||
"name": "string",
|
||||
"options": [
|
||||
|
@ -4395,6 +4398,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
}
|
||||
],
|
||||
"template_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
|
||||
"type": "string",
|
||||
"values": [
|
||||
{
|
||||
"count": 0,
|
||||
|
@ -4420,6 +4424,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
|
||||
```json
|
||||
{
|
||||
"description": "string",
|
||||
"display_name": "string",
|
||||
"name": "string",
|
||||
"options": [
|
||||
|
@ -4431,6 +4436,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
}
|
||||
],
|
||||
"template_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
|
||||
"type": "string",
|
||||
"values": [
|
||||
{
|
||||
"count": 0,
|
||||
|
@ -4444,10 +4450,12 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
| -------------- | ------------------------------------------------------------------------------------------- | -------- | ------------ | ----------- |
|
||||
| `description` | string | false | | |
|
||||
| `display_name` | string | false | | |
|
||||
| `name` | string | false | | |
|
||||
| `options` | array of [codersdk.TemplateVersionParameterOption](#codersdktemplateversionparameteroption) | false | | |
|
||||
| `template_ids` | array of string | false | | |
|
||||
| `type` | string | false | | |
|
||||
| `values` | array of [codersdk.TemplateParameterValue](#codersdktemplateparametervalue) | false | | |
|
||||
|
||||
## codersdk.TemplateParameterValue
|
||||
|
|
|
@ -987,6 +987,8 @@ export interface TemplateParameterUsage {
|
|||
readonly template_ids: string[]
|
||||
readonly display_name: string
|
||||
readonly name: string
|
||||
readonly type: string
|
||||
readonly description: string
|
||||
readonly options?: TemplateVersionParameterOption[]
|
||||
readonly values: TemplateParameterValue[]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue