feat: Expose managed variables via API (#6134)

* 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
This commit is contained in:
Marcin Tojek
2023-02-15 18:24:15 +01:00
committed by GitHub
parent f0f39b4892
commit 3b7b96ac28
41 changed files with 2423 additions and 667 deletions

View File

@ -133,6 +133,7 @@ type createValidTemplateVersionArgs struct {
Provisioner database.ProvisionerType
FileID uuid.UUID
ParameterFile string
ValuesFile string
// Template is only required if updating a template's active version.
Template *codersdk.Template
// ReuseParameters will attempt to reuse params from the Template field
@ -145,13 +146,21 @@ type createValidTemplateVersionArgs struct {
func createValidTemplateVersion(cmd *cobra.Command, args createValidTemplateVersionArgs, parameters ...codersdk.CreateParameterRequest) (*codersdk.TemplateVersion, []codersdk.CreateParameterRequest, error) {
client := args.Client
// FIXME(mtojek): I will iterate on CLI experience in the follow-up.
// see: https://github.com/coder/coder/issues/5980
variableValues, err := loadVariableValues(args.ValuesFile)
if err != nil {
return nil, nil, err
}
req := codersdk.CreateTemplateVersionRequest{
Name: args.Name,
StorageMethod: codersdk.ProvisionerStorageMethodFile,
FileID: args.FileID,
Provisioner: codersdk.ProvisionerType(args.Provisioner),
ParameterValues: parameters,
ProvisionerTags: args.ProvisionerTags,
Name: args.Name,
StorageMethod: codersdk.ProvisionerStorageMethodFile,
FileID: args.FileID,
Provisioner: codersdk.ProvisionerType(args.Provisioner),
ParameterValues: parameters,
ProvisionerTags: args.ProvisionerTags,
UserVariableValues: variableValues,
}
if args.Template != nil {
req.TemplateID = args.Template.ID

View File

@ -93,6 +93,7 @@ func templatePush() *cobra.Command {
versionName string
provisioner string
parameterFile string
valuesFile string
alwaysPrompt bool
provisionerTags []string
uploadFlags templateUploadFlags
@ -139,6 +140,7 @@ func templatePush() *cobra.Command {
Provisioner: database.ProvisionerType(provisioner),
FileID: resp.ID,
ParameterFile: parameterFile,
ValuesFile: valuesFile,
Template: &template,
ReuseParameters: !alwaysPrompt,
ProvisionerTags: tags,
@ -165,6 +167,7 @@ func templatePush() *cobra.Command {
cmd.Flags().StringVarP(&provisioner, "test.provisioner", "", "terraform", "Customize the provisioner backend")
cmd.Flags().StringVarP(&parameterFile, "parameter-file", "", "", "Specify a file path with parameter values.")
cmd.Flags().StringVarP(&valuesFile, "values-file", "", "", "Specify a file path with values for managed variables.")
cmd.Flags().StringVarP(&versionName, "name", "", "", "Specify a name for the new template version. It will be automatically generated if not provided.")
cmd.Flags().StringArrayVarP(&provisionerTags, "provisioner-tag", "", []string{}, "Specify a set of tags to target provisioner daemons.")
cmd.Flags().BoolVar(&alwaysPrompt, "always-prompt", false, "Always prompt all parameters. Does not pull parameter values from active template version")

50
cli/templatevariables.go Normal file
View File

@ -0,0 +1,50 @@
package cli
import (
"os"
"golang.org/x/xerrors"
"gopkg.in/yaml.v3"
"github.com/coder/coder/codersdk"
)
func loadVariableValues(variablesFile string) ([]codersdk.VariableValue, error) {
var values []codersdk.VariableValue
if variablesFile == "" {
return values, nil
}
variablesMap, err := createVariablesMapFromFile(variablesFile)
if err != nil {
return nil, err
}
for name, value := range variablesMap {
values = append(values, codersdk.VariableValue{
Name: name,
Value: value,
})
}
return values, nil
}
// Reads a YAML file and populates a string -> string map.
// Throws an error if the file name is empty.
func createVariablesMapFromFile(variablesFile string) (map[string]string, error) {
if variablesFile == "" {
return nil, xerrors.Errorf("variable file name is not specified")
}
variablesMap := make(map[string]string)
variablesFileContents, err := os.ReadFile(variablesFile)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(variablesFileContents, &variablesMap)
if err != nil {
return nil, err
}
return variablesMap, nil
}

View File

@ -13,6 +13,7 @@ Flags:
automatically generated if not provided.
--parameter-file string Specify a file path with parameter values.
--provisioner-tag stringArray Specify a set of tags to target provisioner daemons.
--values-file string Specify a file path with values for managed variables.
-y, --yes Bypass prompts
Global Flags: