feat: add workflow template and updated workspace template parameter logic to replace select.nodepool values with runtime values.

This commit is contained in:
Andrey Melnikov
2020-12-19 20:52:52 -08:00
parent b2bf62d932
commit 5e7c5ba888
4 changed files with 131 additions and 2 deletions

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/onepanelio/core/pkg/util/ptr"
"github.com/onepanelio/core/pkg/util/request"
pagination "github.com/onepanelio/core/pkg/util/request/pagination"
"strconv"
@@ -32,6 +33,38 @@ func (wt *WorkflowTemplateFilter) GetLabels() []*Label {
return wt.Labels
}
// replaceSysNodePoolOptions replaces a select.nodepool parameter with the nodePool options in the systemConfig
// and returns the new parameters with the change.
func (c *Client) replaceSysNodePoolOptions(parameters []Parameter) (result []Parameter, err error) {
nodePoolOptions, err := c.systemConfig.NodePoolOptions()
if err != nil {
return result, err
}
nodePoolParameterOptions := make([]*ParameterOption, 0)
for _, option := range nodePoolOptions {
nodePoolParameterOptions = append(nodePoolParameterOptions, &ParameterOption{
Name: option.Name,
Value: option.Value,
})
}
for i := range parameters {
param := parameters[i]
if param.Type == "select.nodepool" {
param.Options = nodePoolParameterOptions
if param.Value != nil && *param.Value == "default" {
param.Value = ptr.String(param.Options[0].Value)
}
}
result = append(result, param)
}
return
}
func applyWorkflowTemplateFilter(sb sq.SelectBuilder, request *request.Request) (sq.SelectBuilder, error) {
if !request.HasFilter() {
return sb, nil
@@ -390,6 +423,30 @@ func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (work
}
workflowTemplate.Parameters = wtv.Parameters
nodePoolOptions, err := c.systemConfig.NodePoolOptions()
if err != nil {
return nil, err
}
nodePoolParameterOptions := make([]*ParameterOption, 0)
for _, option := range nodePoolOptions {
nodePoolParameterOptions = append(nodePoolParameterOptions, &ParameterOption{
Name: option.Name,
Value: option.Value,
})
}
for i := range workflowTemplate.Parameters {
param := &workflowTemplate.Parameters[i]
if param.Type == "select.nodepool" {
param.Options = nodePoolParameterOptions
if param.Value != nil && *param.Value == "default" {
param.Value = ptr.String(param.Options[0].Value)
}
}
}
return workflowTemplate, nil
}
@@ -1061,3 +1118,42 @@ func (c *Client) GetWorkflowTemplateLabels(namespace, name, prefix string, versi
return
}
// GenerateWorkflowTemplate replaces any special parameters with runtime values
func (c *Client) GenerateWorkflowTemplateManifest(manifest string) (string, error) {
manifestObject := make(map[string]interface{})
if err := yaml.Unmarshal([]byte(manifest), &manifestObject); err != nil {
return "", util.NewUserError(codes.InvalidArgument, "Invalid yaml")
}
argumentsRaw := manifestObject["arguments"]
arguments, ok := argumentsRaw.(map[string]interface{})
if !ok {
return "", fmt.Errorf("unable to parse arguments")
}
jsonParameters, err := json.Marshal(arguments["parameters"])
if err != nil {
return "", err
}
parameters := make([]Parameter, 0)
if err := json.Unmarshal(jsonParameters, &parameters); err != nil {
return "", err
}
parameters, err = c.replaceSysNodePoolOptions(parameters)
if err != nil {
return "", err
}
arguments["parameters"] = parameters
manifestObject["arguments"] = arguments
finalManifest, err := yaml.Marshal(manifestObject)
if err != nil {
return "", err
}
return string(finalManifest), err
}

View File

@@ -945,6 +945,12 @@ func (c *Client) generateWorkspaceTemplateWorkflowTemplate(workspaceTemplate *Wo
return nil, util.NewUserError(codes.InvalidArgument, err.Error())
}
modifiedParameters, err := c.replaceSysNodePoolOptions(workspaceSpec.Arguments.Parameters)
if err != nil {
return nil, err
}
workspaceSpec.Arguments.Parameters = modifiedParameters
if err = generateArguments(workspaceSpec, config); err != nil {
return nil, err
}

View File

@@ -47,6 +47,34 @@ func apiWorkflowTemplate(wft *v1.WorkflowTemplate) *api.WorkflowTemplate {
return res
}
// GenerateWorkflowTemplate generates a workflow template, applying any modifications based on the content of the manifest
func (s *WorkflowTemplateServer) GenerateWorkflowTemplate(ctx context.Context, req *api.GenerateWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "get", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
if req.WorkflowTemplate.Manifest == "" {
return &api.WorkflowTemplate{
Manifest: "",
}, nil
}
finalManifest, err := client.GenerateWorkflowTemplateManifest(req.WorkflowTemplate.Manifest)
if err != nil {
return &api.WorkflowTemplate{
Manifest: "",
}, err
}
workflowTemplate := &v1.WorkflowTemplate{
Manifest: finalManifest,
}
return apiWorkflowTemplate(workflowTemplate), nil
}
// CreateWorkflowTemplate creates a workflow template and the initial version
func (s *WorkflowTemplateServer) CreateWorkflowTemplate(ctx context.Context, req *api.CreateWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
client := getClient(ctx)

View File

@@ -61,8 +61,7 @@ func (s WorkspaceTemplateServer) GenerateWorkspaceTemplateWorkflowTemplate(ctx c
Manifest: req.WorkspaceTemplate.Manifest,
}
workflowTemplate, err := client.GenerateWorkspaceTemplateWorkflowTemplate(workspaceTemplate)
if workflowTemplate == nil {
if err != nil || workflowTemplate == nil {
return &api.WorkflowTemplate{
Manifest: "",
}, err