mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
Use richer `previewtypes.Parameter` for `wsbuilder`. This is a pre-requirement to adding dynamic parameter validation. The richer type contains more information than the `db` parameter, so the conversion is lossless.
148 lines
4.5 KiB
Go
148 lines
4.5 KiB
Go
package dynamicparameters
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/hashicorp/hcl/v2"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/database/db2sdk"
|
|
"github.com/coder/coder/v2/coderd/util/ptr"
|
|
sdkproto "github.com/coder/coder/v2/provisionersdk/proto"
|
|
"github.com/coder/preview"
|
|
previewtypes "github.com/coder/preview/types"
|
|
"github.com/coder/terraform-provider-coder/v2/provider"
|
|
)
|
|
|
|
type staticRender struct {
|
|
staticParams []previewtypes.Parameter
|
|
}
|
|
|
|
func (r *loader) staticRender(ctx context.Context, db database.Store) (*staticRender, error) {
|
|
dbTemplateVersionParameters, err := db.GetTemplateVersionParameters(ctx, r.templateVersionID)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("template version parameters: %w", err)
|
|
}
|
|
|
|
params := db2sdk.List(dbTemplateVersionParameters, TemplateVersionParameter)
|
|
|
|
for i, param := range params {
|
|
// Update the diagnostics to validate the 'default' value.
|
|
// We do not have a user supplied value yet, so we use the default.
|
|
params[i].Diagnostics = append(params[i].Diagnostics, previewtypes.Diagnostics(param.Valid(param.Value))...)
|
|
}
|
|
return &staticRender{
|
|
staticParams: params,
|
|
}, nil
|
|
}
|
|
|
|
func (r *staticRender) Render(_ context.Context, _ uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) {
|
|
params := r.staticParams
|
|
for i := range params {
|
|
param := ¶ms[i]
|
|
paramValue, ok := values[param.Name]
|
|
if ok {
|
|
param.Value = previewtypes.StringLiteral(paramValue)
|
|
} else {
|
|
param.Value = param.DefaultValue
|
|
}
|
|
param.Diagnostics = previewtypes.Diagnostics(param.Valid(param.Value))
|
|
}
|
|
|
|
return &preview.Output{
|
|
Parameters: params,
|
|
}, hcl.Diagnostics{
|
|
{
|
|
// Only a warning because the form does still work.
|
|
Severity: hcl.DiagWarning,
|
|
Summary: "This template version is missing required metadata to support dynamic parameters.",
|
|
Detail: "To restore full functionality, please re-import the terraform as a new template version.",
|
|
},
|
|
}
|
|
}
|
|
|
|
func (*staticRender) Close() {}
|
|
|
|
func TemplateVersionParameter(it database.TemplateVersionParameter) previewtypes.Parameter {
|
|
param := previewtypes.Parameter{
|
|
ParameterData: previewtypes.ParameterData{
|
|
Name: it.Name,
|
|
DisplayName: it.DisplayName,
|
|
Description: it.Description,
|
|
Type: previewtypes.ParameterType(it.Type),
|
|
FormType: provider.ParameterFormType(it.FormType),
|
|
Styling: previewtypes.ParameterStyling{},
|
|
Mutable: it.Mutable,
|
|
DefaultValue: previewtypes.StringLiteral(it.DefaultValue),
|
|
Icon: it.Icon,
|
|
Options: make([]*previewtypes.ParameterOption, 0),
|
|
Validations: make([]*previewtypes.ParameterValidation, 0),
|
|
Required: it.Required,
|
|
Order: int64(it.DisplayOrder),
|
|
Ephemeral: it.Ephemeral,
|
|
Source: nil,
|
|
},
|
|
// Always use the default, since we used to assume the empty string
|
|
Value: previewtypes.StringLiteral(it.DefaultValue),
|
|
Diagnostics: make(previewtypes.Diagnostics, 0),
|
|
}
|
|
|
|
if it.ValidationError != "" || it.ValidationRegex != "" || it.ValidationMonotonic != "" {
|
|
var reg *string
|
|
if it.ValidationRegex != "" {
|
|
reg = ptr.Ref(it.ValidationRegex)
|
|
}
|
|
|
|
var vMin *int64
|
|
if it.ValidationMin.Valid {
|
|
vMin = ptr.Ref(int64(it.ValidationMin.Int32))
|
|
}
|
|
|
|
var vMax *int64
|
|
if it.ValidationMax.Valid {
|
|
vMax = ptr.Ref(int64(it.ValidationMax.Int32))
|
|
}
|
|
|
|
var monotonic *string
|
|
if it.ValidationMonotonic != "" {
|
|
monotonic = ptr.Ref(it.ValidationMonotonic)
|
|
}
|
|
|
|
param.Validations = append(param.Validations, &previewtypes.ParameterValidation{
|
|
Error: it.ValidationError,
|
|
Regex: reg,
|
|
Min: vMin,
|
|
Max: vMax,
|
|
Monotonic: monotonic,
|
|
})
|
|
}
|
|
|
|
var protoOptions []*sdkproto.RichParameterOption
|
|
err := json.Unmarshal(it.Options, &protoOptions)
|
|
if err != nil {
|
|
param.Diagnostics = append(param.Diagnostics, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Failed to parse json parameter options",
|
|
Detail: err.Error(),
|
|
})
|
|
}
|
|
|
|
for _, opt := range protoOptions {
|
|
param.Options = append(param.Options, &previewtypes.ParameterOption{
|
|
Name: opt.Name,
|
|
Description: opt.Description,
|
|
Value: previewtypes.StringLiteral(opt.Value),
|
|
Icon: opt.Icon,
|
|
})
|
|
}
|
|
|
|
// Take the form type from the ValidateFormType function. This is a bit
|
|
// unfortunate we have to do this, but it will return the default form_type
|
|
// for a given set of conditions.
|
|
_, param.FormType, _ = provider.ValidateFormType(provider.OptionType(param.Type), len(param.Options), param.FormType)
|
|
return param
|
|
}
|