feat: Update CLI to handle managed variables (#6220)

* WIP

* hcl

* useManagedVariables

* fix

* Fix

* Fix

* fix

* go:build

* Fix

* fix: bool flag

* Insert template variables

* API

* fix

* Expose via API

* More wiring

* CLI for testing purposes

* WIP

* Delete FIXME

* planVars

* WIP

* WIP

* UserVariableValues

* no dry run

* Dry run

* Done FIXME

* Fix

* Fix: CLI

* Fix: migration

* API tests

* Test info

* Tests

* More tests

* fix: lint

* Fix: authz

* Address PR comments

* Fix

* fix

* fix

* CLI: create

* unit tests: create templates with variables

* Use last variables

* Fix

* Fix

* Fix

* Push tests

* fix: variable is required if Default is nil

* WIP

* Redact sensitive values

* Fixes

* Fixes

* Fix: arg description

* Fix

* Variable param

* Fix: gen

* Fix

* Fix: goldens
This commit is contained in:
Marcin Tojek
2023-02-17 09:07:45 +01:00
committed by GitHub
parent d5af536ea2
commit a69137b1f7
15 changed files with 626 additions and 24 deletions

View File

@ -264,9 +264,14 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac
return nil, failJob(fmt.Sprintf("unmarshal job input %q: %s", job.Input, err))
}
userVariableValues, err := server.includeLastVariableValues(ctx, input.TemplateVersionID, input.UserVariableValues)
if err != nil {
return nil, failJob(err.Error())
}
protoJob.Type = &proto.AcquiredJob_TemplateImport_{
TemplateImport: &proto.AcquiredJob_TemplateImport{
UserVariableValues: convertVariableValues(input.UserVariableValues),
UserVariableValues: convertVariableValues(userVariableValues),
Metadata: &sdkproto.Provision_Metadata{
CoderUrl: server.AccessURL.String(),
},
@ -290,6 +295,58 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac
return protoJob, err
}
func (server *Server) includeLastVariableValues(ctx context.Context, templateVersionID uuid.UUID, userVariableValues []codersdk.VariableValue) ([]codersdk.VariableValue, error) {
var values []codersdk.VariableValue
values = append(values, userVariableValues...)
if templateVersionID == uuid.Nil {
return values, nil
}
templateVersion, err := server.Database.GetTemplateVersionByID(ctx, templateVersionID)
if err != nil {
return nil, fmt.Errorf("get template version: %w", err)
}
if templateVersion.TemplateID.UUID == uuid.Nil {
return values, nil
}
template, err := server.Database.GetTemplateByID(ctx, templateVersion.TemplateID.UUID)
if err != nil {
return nil, fmt.Errorf("get template: %w", err)
}
if template.ActiveVersionID == uuid.Nil {
return values, nil
}
templateVariables, err := server.Database.GetTemplateVersionVariables(ctx, template.ActiveVersionID)
if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("get template version variables: %w", err)
}
for _, templateVariable := range templateVariables {
var alreadyAdded bool
for _, uvv := range userVariableValues {
if uvv.Name == templateVariable.Name {
alreadyAdded = true
break
}
}
if alreadyAdded {
continue
}
values = append(values, codersdk.VariableValue{
Name: templateVariable.Name,
Value: templateVariable.Value,
})
}
return values, nil
}
func (server *Server) CommitQuota(ctx context.Context, request *proto.CommitQuotaRequest) (*proto.CommitQuotaResponse, error) {
//nolint:gocritic // Provisionerd has specific authz rules.
ctx = dbauthz.AsProvisionerd(ctx)
@ -1222,8 +1279,9 @@ func convertVariableValues(variableValues []codersdk.VariableValue) []*sdkproto.
protoVariableValues := make([]*sdkproto.VariableValue, len(variableValues))
for i, variableValue := range variableValues {
protoVariableValues[i] = &sdkproto.VariableValue{
Name: variableValue.Name,
Value: variableValue.Value,
Name: variableValue.Name,
Value: variableValue.Value,
Sensitive: true, // Without the template variable schema we have to assume that every variable may be sensitive.
}
}
return protoVariableValues

View File

@ -316,7 +316,7 @@ func TestAcquireJob(t *testing.T) {
want, err := json.Marshal(&proto.AcquiredJob_TemplateImport_{
TemplateImport: &proto.AcquiredJob_TemplateImport{
UserVariableValues: []*sdkproto.VariableValue{
{Name: "first", Value: "first_value"},
{Name: "first", Sensitive: true, Value: "first_value"},
},
Metadata: &sdkproto.Provision_Metadata{
CoderUrl: srv.AccessURL.String(),

View File

@ -1531,8 +1531,10 @@ func convertTemplateVersionVariables(dbVariables []database.TemplateVersionVaria
return variables
}
const redacted = "*redacted*"
func convertTemplateVersionVariable(variable database.TemplateVersionVariable) codersdk.TemplateVersionVariable {
return codersdk.TemplateVersionVariable{
templateVariable := codersdk.TemplateVersionVariable{
Name: variable.Name,
Description: variable.Description,
Type: variable.Type,
@ -1541,6 +1543,11 @@ func convertTemplateVersionVariable(variable database.TemplateVersionVariable) c
Required: variable.Required,
Sensitive: variable.Sensitive,
}
if templateVariable.Sensitive {
templateVariable.Value = redacted
templateVariable.DefaultValue = redacted
}
return templateVariable
}
func watchTemplateChannel(id uuid.UUID) string {

View File

@ -1132,7 +1132,6 @@ func TestTemplateVersionVariables(t *testing.T) {
Description: "This is the first variable",
Type: "string",
Required: true,
Sensitive: true,
},
}
const firstVariableValue = "foobar"
@ -1180,7 +1179,6 @@ func TestTemplateVersionVariables(t *testing.T) {
Description: "This is the first variable",
Type: "string",
Required: true,
Sensitive: true,
},
{
Name: "second_variable",
@ -1218,4 +1216,52 @@ func TestTemplateVersionVariables(t *testing.T) {
require.Equal(t, "", actualVariables[0].Value)
require.Equal(t, templateVariables[1].DefaultValue, actualVariables[1].Value)
})
t.Run("Redact sensitive variables", func(t *testing.T) {
t.Parallel()
templateVariables := []*proto.TemplateVariable{
{
Name: "first_variable",
Description: "This is the first variable",
Type: "string",
Required: true,
Sensitive: true,
},
}
const firstVariableValue = "foobar"
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID,
createEchoResponses(templateVariables),
func(ctvr *codersdk.CreateTemplateVersionRequest) {
ctvr.UserVariableValues = []codersdk.VariableValue{
{
Name: templateVariables[0].Name,
Value: firstVariableValue,
},
}
},
)
templateVersion := coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
// As user passed the value for the first parameter, the job will succeed.
require.Empty(t, templateVersion.Job.Error)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
defer cancel()
actualVariables, err := client.TemplateVersionVariables(ctx, templateVersion.ID)
require.NoError(t, err)
require.Len(t, actualVariables, 1)
require.Equal(t, templateVariables[0].Name, actualVariables[0].Name)
require.Equal(t, templateVariables[0].Description, actualVariables[0].Description)
require.Equal(t, templateVariables[0].Type, actualVariables[0].Type)
require.Equal(t, templateVariables[0].Required, actualVariables[0].Required)
require.Equal(t, templateVariables[0].Sensitive, actualVariables[0].Sensitive)
require.Equal(t, "*redacted*", actualVariables[0].DefaultValue)
require.Equal(t, "*redacted*", actualVariables[0].Value)
})
}