Skip to content

Commit

Permalink
WorkflowTemplate CRD (argoproj#1312)
Browse files Browse the repository at this point in the history
  • Loading branch information
dtaniwaki authored and Duske committed Aug 15, 2019
1 parent b1893d5 commit 1169158
Show file tree
Hide file tree
Showing 60 changed files with 3,196 additions and 255 deletions.
106 changes: 105 additions & 1 deletion api/openapi-spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@
"description": "Name of template to execute",
"type": "string"
},
"templateRef": {
"description": "TemplateRef is the reference to the template resource to execute.",
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.TemplateRef"
},
"when": {
"description": "When is an expression in which the task should conditionally execute",
"type": "string"
Expand Down Expand Up @@ -839,6 +843,10 @@
"description": "Location in which all files related to the step will be stored (logs, artifacts, etc...). Can be overridden by individual items in Outputs. If omitted, will use the default artifact repository location configured in the controller, appended with the \u003cworkflowname\u003e/\u003cnodename\u003e in the key.",
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.ArtifactLocation"
},
"arguments": {
"description": "Arguments hold arguments to the template.",
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.Arguments"
},
"container": {
"description": "Container is the main container image to run in the pod",
"$ref": "#/definitions/io.k8s.api.core.v1.Container"
Expand Down Expand Up @@ -947,6 +955,14 @@
"description": "Suspend template subtype which can suspend a workflow when reaching the step",
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.SuspendTemplate"
},
"template": {
"description": "Template is the name of the template which is used as the base of this template.",
"type": "string"
},
"templateRef": {
"description": "TemplateRef is the reference to the template resource which is used as the base of this template.",
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.TemplateRef"
},
"tolerations": {
"description": "Tolerations to apply to workflow pods.",
"type": "array",
Expand All @@ -963,6 +979,23 @@
}
}
},
"io.argoproj.workflow.v1alpha1.TemplateRef": {
"description": "TemplateRef is a reference of template resource.",
"properties": {
"name": {
"description": "Name is the resource name of the template.",
"type": "string"
},
"runtimeResolution": {
"description": "RuntimeResolution skips validation at creation time. By enabling this option, you can create the referred workflow template before the actual runtime.",
"type": "boolean"
},
"template": {
"description": "Template is the name of referred template in the resource.",
"type": "string"
}
}
},
"io.argoproj.workflow.v1alpha1.UserContainer": {
"description": "UserContainer is a container specified by a user.",
"required": [
Expand Down Expand Up @@ -1313,9 +1346,13 @@
"type": "string"
},
"template": {
"description": "Template is a reference to the template to execute as the step",
"description": "Template is the name of the template to execute as the step",
"type": "string"
},
"templateRef": {
"description": "TemplateRef is the reference to the template resource to execute as the step.",
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.TemplateRef"
},
"when": {
"description": "When is an expression in which the step should conditionally execute",
"type": "string"
Expand All @@ -1336,6 +1373,73 @@
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.Sequence"
}
}
},
"io.argoproj.workflow.v1alpha1.WorkflowTemplate": {
"description": "WorkflowTemplate is the definition of a workflow template resource",
"required": [
"spec"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
},
"spec": {
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.WorkflowTemplateSpec"
}
}
},
"io.argoproj.workflow.v1alpha1.WorkflowTemplateList": {
"description": "WorkflowTemplateList is list of WorkflowTemplate resources",
"required": [
"metadata",
"items"
],
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.WorkflowTemplate"
}
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta"
}
}
},
"io.argoproj.workflow.v1alpha1.WorkflowTemplateSpec": {
"description": "WorkflowTemplateSpec is a spec of WorkflowTemplate.",
"required": [
"templates"
],
"properties": {
"arguments": {
"description": "Arguments hold arguments to the template.",
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.Arguments"
},
"templates": {
"description": "Templates is a list of workflow templates.",
"type": "array",
"items": {
"$ref": "#/definitions/io.argoproj.workflow.v1alpha1.Template"
}
}
}
}
}
}
6 changes: 3 additions & 3 deletions cmd/argo/commands/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"strings"

wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
wfclientset "github.com/argoproj/argo/pkg/client/clientset/versioned"
versioned "github.com/argoproj/argo/pkg/client/clientset/versioned"
"github.com/argoproj/argo/pkg/client/clientset/versioned/typed/workflow/v1alpha1"
"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes"
Expand All @@ -21,7 +21,7 @@ var (
restConfig *rest.Config
clientConfig clientcmd.ClientConfig
clientset *kubernetes.Clientset
wfClientset *wfclientset.Clientset // wfClientset is used for the server-dry-run submit option
wfClientset *versioned.Clientset
wfClient v1alpha1.WorkflowInterface
jobStatusIconMap map[wfv1.NodePhase]string
noColor bool
Expand Down Expand Up @@ -95,7 +95,7 @@ func InitWorkflowClient(ns ...string) v1alpha1.WorkflowInterface {
log.Fatal(err)
}
}
wfClientset = wfclientset.NewForConfigOrDie(restConfig)
wfClientset = versioned.NewForConfigOrDie(restConfig)
wfClient = wfClientset.ArgoprojV1alpha1().Workflows(namespace)
return wfClient
}
Expand Down
5 changes: 5 additions & 0 deletions cmd/argo/commands/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ func printNode(w *tabwriter.Writer, wf *wfv1.Workflow, node wfv1.NodeStatus, dep
return
}
nodeName := fmt.Sprintf("%s %s", jobStatusIconMap[node.Phase], node.DisplayName)
if node.TemplateRef != nil {
nodeName = fmt.Sprintf("%s (%s/%s)", nodeName, node.TemplateRef.Name, node.TemplateRef.Template)
} else if node.TemplateName != "" {
nodeName = fmt.Sprintf("%s (%s)", nodeName, node.TemplateName)
}
var args []interface{}
duration := humanize.RelativeDurationShort(node.StartedAt.Time, node.FinishedAt.Time)
if node.Type == wfv1.NodeTypePod {
Expand Down
11 changes: 8 additions & 3 deletions cmd/argo/commands/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,20 @@ func NewLintCommand() *cobra.Command {
cmd.HelpFunc()(cmd, args)
os.Exit(1)
}

namespace, _, err := clientConfig.Namespace()
if err != nil {
log.Fatal(err)
}

validateDir := cmdutil.MustIsDir(args[0])
var err error
if validateDir {
if len(args) > 1 {
fmt.Printf("Validation of a single directory supported")
os.Exit(1)
}
fmt.Printf("Verifying all workflow manifests in directory: %s\n", args[0])
err = validate.LintWorkflowDir(args[0], strict)
err = validate.LintWorkflowDir(wfClientset, namespace, args[0], strict)
} else {
yamlFiles := make([]string, 0)
for _, filePath := range args {
Expand All @@ -42,7 +47,7 @@ func NewLintCommand() *cobra.Command {
yamlFiles = append(yamlFiles, filePath)
}
for _, yamlFile := range yamlFiles {
err = validate.LintWorkflowFile(yamlFile, strict)
err = validate.LintWorkflowFile(wfClientset, namespace, yamlFile, strict)
if err != nil {
break
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/argo/commands/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func countPendingRunningCompleted(wf *wfv1.Workflow) (int, int, int) {
log.Fatal(err)
}
for _, node := range wf.Status.Nodes {
tmpl := wf.GetTemplate(node.TemplateName)
tmpl := wf.GetTemplateByName(node.TemplateName)
if tmpl == nil || !tmpl.IsPodType() {
continue
}
Expand Down
8 changes: 7 additions & 1 deletion cmd/argo/commands/resubmit.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import (
"log"
"os"

"github.com/argoproj/argo/workflow/util"
Expand All @@ -23,12 +24,17 @@ func NewResubmitCommand() *cobra.Command {
os.Exit(1)
}

namespace, _, err := clientConfig.Namespace()
if err != nil {
log.Fatal(err)
}

wfClient := InitWorkflowClient()
wf, err := wfClient.Get(args[0], metav1.GetOptions{})
errors.CheckError(err)
newWF, err := util.FormulateResubmitWorkflow(wf, memoized)
errors.CheckError(err)
created, err := util.SubmitWorkflow(wfClient, wfClientset, newWF, nil)
created, err := util.SubmitWorkflow(wfClient, wfClientset, namespace, newWF, nil)
errors.CheckError(err)
printWorkflow(created, cliSubmitOpts.output, DefaultStatus)
waitOrWatch([]string{created.Name}, cliSubmitOpts)
Expand Down
2 changes: 2 additions & 0 deletions cmd/argo/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package commands
import (
"os"

"github.com/argoproj/argo/cmd/argo/commands/template"
"github.com/argoproj/argo/util/cmd"
"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
Expand Down Expand Up @@ -38,6 +39,7 @@ func NewCommand() *cobra.Command {
command.AddCommand(NewWatchCommand())
command.AddCommand(NewTerminateCommand())
command.AddCommand(cmd.NewVersionCmd(CLIName))
command.AddCommand(template.NewTemplateCommand())

addKubectlFlagsToCmd(command)
return command
Expand Down
4 changes: 2 additions & 2 deletions cmd/argo/commands/submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c
}
wf.Namespace = namespace
}
created, err := util.SubmitWorkflow(wfClient, wfClientset, &wf, submitOpts)
created, err := util.SubmitWorkflow(wfClient, wfClientset, namespace, &wf, submitOpts)
if err != nil {
log.Fatalf("Failed to submit workflow: %v", err)
}
Expand Down Expand Up @@ -223,7 +223,7 @@ func unmarshalWorkflows(wfBytes []byte, strict bool) []wfv1.Workflow {
if err == nil {
return []wfv1.Workflow{wf}
}
yamlWfs, err := common.SplitYAMLFile(wfBytes, strict)
yamlWfs, err := common.SplitWorkflowYAMLFile(wfBytes, strict)
if err == nil {
return yamlWfs
}
Expand Down
59 changes: 59 additions & 0 deletions cmd/argo/commands/template/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package template

import (
"log"

versioned "github.com/argoproj/argo/pkg/client/clientset/versioned"
"github.com/argoproj/argo/pkg/client/clientset/versioned/typed/workflow/v1alpha1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

// Global variables
var (
restConfig *rest.Config
clientConfig clientcmd.ClientConfig
clientset *kubernetes.Clientset
wfClientset *versioned.Clientset
wftmplClient v1alpha1.WorkflowTemplateInterface
namespace string
)

func initKubeClient() *kubernetes.Clientset {
if clientset != nil {
return clientset
}
var err error
restConfig, err = clientConfig.ClientConfig()
if err != nil {
log.Fatal(err)
}

// create the clientset
clientset, err = kubernetes.NewForConfig(restConfig)
if err != nil {
log.Fatal(err)
}
return clientset
}

// InitWorkflowTemplateClient creates a new client for the Kubernetes WorkflowTemplate CRD.
func InitWorkflowTemplateClient(ns ...string) v1alpha1.WorkflowTemplateInterface {
if wftmplClient != nil {
return wftmplClient
}
initKubeClient()
var err error
if len(ns) > 0 {
namespace = ns[0]
} else {
namespace, _, err = clientConfig.Namespace()
if err != nil {
log.Fatal(err)
}
}
wfClientset = versioned.NewForConfigOrDie(restConfig)
wftmplClient = wfClientset.ArgoprojV1alpha1().WorkflowTemplates(namespace)
return wftmplClient
}
Loading

0 comments on commit 1169158

Please sign in to comment.