mirror of https://github.com/coder/coder.git
117 lines
3.2 KiB
Go
117 lines
3.2 KiB
Go
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"golang.org/x/xerrors"
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"github.com/coder/coder/v2/codersdk"
|
|
"github.com/coder/serpent"
|
|
)
|
|
|
|
// workspaceParameterFlags are used by commands processing rich parameters and/or build options.
|
|
type workspaceParameterFlags struct {
|
|
promptBuildOptions bool
|
|
buildOptions []string
|
|
|
|
richParameterFile string
|
|
richParameters []string
|
|
|
|
promptRichParameters bool
|
|
}
|
|
|
|
func (wpf *workspaceParameterFlags) allOptions() []serpent.Option {
|
|
options := append(wpf.cliBuildOptions(), wpf.cliParameters()...)
|
|
return append(options, wpf.alwaysPrompt())
|
|
}
|
|
|
|
func (wpf *workspaceParameterFlags) cliBuildOptions() []serpent.Option {
|
|
return serpent.OptionSet{
|
|
{
|
|
Flag: "build-option",
|
|
Env: "CODER_BUILD_OPTION",
|
|
Description: `Build option value in the format "name=value".`,
|
|
Value: serpent.StringArrayOf(&wpf.buildOptions),
|
|
},
|
|
{
|
|
Flag: "build-options",
|
|
Description: "Prompt for one-time build options defined with ephemeral parameters.",
|
|
Value: serpent.BoolOf(&wpf.promptBuildOptions),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (wpf *workspaceParameterFlags) cliParameters() []serpent.Option {
|
|
return serpent.OptionSet{
|
|
serpent.Option{
|
|
Flag: "parameter",
|
|
Env: "CODER_RICH_PARAMETER",
|
|
Description: `Rich parameter value in the format "name=value".`,
|
|
Value: serpent.StringArrayOf(&wpf.richParameters),
|
|
},
|
|
serpent.Option{
|
|
Flag: "rich-parameter-file",
|
|
Env: "CODER_RICH_PARAMETER_FILE",
|
|
Description: "Specify a file path with values for rich parameters defined in the template.",
|
|
Value: serpent.StringOf(&wpf.richParameterFile),
|
|
},
|
|
}
|
|
}
|
|
|
|
func (wpf *workspaceParameterFlags) alwaysPrompt() serpent.Option {
|
|
return serpent.Option{
|
|
Flag: "always-prompt",
|
|
Description: "Always prompt all parameters. Does not pull parameter values from existing workspace.",
|
|
Value: serpent.BoolOf(&wpf.promptRichParameters),
|
|
}
|
|
}
|
|
|
|
func asWorkspaceBuildParameters(nameValuePairs []string) ([]codersdk.WorkspaceBuildParameter, error) {
|
|
var params []codersdk.WorkspaceBuildParameter
|
|
for _, nameValue := range nameValuePairs {
|
|
split := strings.SplitN(nameValue, "=", 2)
|
|
if len(split) < 2 {
|
|
return nil, xerrors.Errorf("format key=value expected, but got %s", nameValue)
|
|
}
|
|
params = append(params, codersdk.WorkspaceBuildParameter{
|
|
Name: split[0],
|
|
Value: split[1],
|
|
})
|
|
}
|
|
return params, nil
|
|
}
|
|
|
|
func parseParameterMapFile(parameterFile string) (map[string]string, error) {
|
|
parameterFileContents, err := os.ReadFile(parameterFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mapStringInterface := make(map[string]interface{})
|
|
err = yaml.Unmarshal(parameterFileContents, &mapStringInterface)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
parameterMap := map[string]string{}
|
|
for k, v := range mapStringInterface {
|
|
switch val := v.(type) {
|
|
case string, bool, int:
|
|
parameterMap[k] = fmt.Sprintf("%v", val)
|
|
case []interface{}:
|
|
b, err := json.Marshal(&val)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
parameterMap[k] = string(b)
|
|
default:
|
|
return nil, xerrors.Errorf("invalid parameter type: %T", v)
|
|
}
|
|
}
|
|
return parameterMap, nil
|
|
}
|