From b0115c853bc7a6a96ae11f8f11755c1b6d9ff5c9 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Sat, 27 Jul 2019 00:20:42 +0200 Subject: [PATCH 01/15] Add DryRun option and pass additional arguments to SubmitWorkflow The additional arguments, wfClientset and namespace, are needed to make the Post request --- workflow/util/util.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/workflow/util/util.go b/workflow/util/util.go index 5b19ea4e7646..d7d73dc98d1e 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -31,6 +31,7 @@ import ( "github.com/argoproj/argo/errors" "github.com/argoproj/argo/pkg/apis/workflow" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" + wfclientset "github.com/argoproj/argo/pkg/client/clientset/versioned" "github.com/argoproj/argo/pkg/client/clientset/versioned/typed/workflow/v1alpha1" cmdutil "github.com/argoproj/argo/util/cmd" "github.com/argoproj/argo/util/file" @@ -141,11 +142,12 @@ type SubmitOpts struct { Parameters []string // --parameter ParameterFile string // --parameter-file ServiceAccount string // --serviceaccount + DryRun bool // --dry-run OwnerReference *metav1.OwnerReference // useful if your custom controller creates argo workflow resources } // SubmitWorkflow validates and submit a single workflow and override some of the fields of the workflow -func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wf *wfv1.Workflow, opts *SubmitOpts) (*wfv1.Workflow, error) { +func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Interface, namespace string, wf *wfv1.Workflow, opts *SubmitOpts) (*wfv1.Workflow, error) { if opts == nil { opts = &SubmitOpts{} } @@ -244,7 +246,21 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wf *wfv1.Workflow, opts *Su if err != nil { return nil, err } - return wfIf.Create(wf) + if opts.DryRun { + // Keep the workflow metadata because it will be removed by the Post request + workflowTypeMeta := wf.TypeMeta + err := wfClientset.ArgoprojV1alpha1().RESTClient().Post(). + Namespace(namespace). + Resource("workflows"). + Body(wf). + Param("dryRun", "All"). + Do(). + Into(wf) + wf.TypeMeta = workflowTypeMeta + return wf, err + } else { + return wfIf.Create(wf) + } } // SuspendWorkflow suspends a workflow by setting spec.suspend to true. Retries conflict errors From 56062e2bdf9b801924acefedef0d0fc05e55ef6b Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Sat, 27 Jul 2019 00:21:36 +0200 Subject: [PATCH 02/15] Add the dry-run flag and use the changed SubmitWorkflow --- cmd/argo/commands/submit.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index a8e1b93af3a6..35ce5c940672 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -52,6 +52,7 @@ func NewSubmitCommand() *cobra.Command { command.Flags().StringArrayVarP(&submitOpts.Parameters, "parameter", "p", []string{}, "pass an input parameter") command.Flags().StringVar(&submitOpts.ServiceAccount, "serviceaccount", "", "run all pods in the workflow using specified serviceaccount") command.Flags().StringVar(&submitOpts.InstanceID, "instanceid", "", "submit with a specific controller's instance id label") + command.Flags().BoolVar(&submitOpts.DryRun, "dry-run", false, "display the declarative form without creating the flow") command.Flags().StringVarP(&cliSubmitOpts.output, "output", "o", "", "Output format. One of: name|json|yaml|wide") command.Flags().BoolVarP(&cliSubmitOpts.wait, "wait", "w", false, "wait for the workflow to complete") command.Flags().BoolVar(&cliSubmitOpts.watch, "watch", false, "watch the workflow until it completes") @@ -117,19 +118,34 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c } } + if submitOpts.DryRun{ + if cliOpts.watch { + log.Fatalf("--watch cannot be combined with --dry-run") + } + if cliOpts.wait { + log.Fatalf("--wait cannot be combined with --dry-run") + } + } + if len(workflows) == 0 { log.Println("No Workflow found in given files") os.Exit(1) } + namespace, _, err := clientConfig.Namespace() + if err != nil { + log.Fatal(err) + } + var workflowNames []string + for _, wf := range workflows { wf.Spec.Priority = cliOpts.priority wfClient := defaultWFClient if wf.Namespace != "" { wfClient = InitWorkflowClient(wf.Namespace) } - created, err := util.SubmitWorkflow(wfClient, &wf, submitOpts) + created, err := util.SubmitWorkflow(wfClient, wfClientset, namespace, &wf, submitOpts) if err != nil { log.Fatalf("Failed to submit workflow: %v", err) } From 24f38520279faa0372649fdf0fe8c49983e7b29e Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Sat, 27 Jul 2019 00:48:55 +0200 Subject: [PATCH 03/15] Rename the clientset variable and make it global --- cmd/argo/commands/common.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/argo/commands/common.go b/cmd/argo/commands/common.go index d54ba101074f..fed9399144d9 100644 --- a/cmd/argo/commands/common.go +++ b/cmd/argo/commands/common.go @@ -21,6 +21,7 @@ var ( restConfig *rest.Config clientConfig clientcmd.ClientConfig clientset *kubernetes.Clientset + wfClientset *wfclientset.Clientset wfClient v1alpha1.WorkflowInterface jobStatusIconMap map[wfv1.NodePhase]string noColor bool @@ -94,8 +95,8 @@ func InitWorkflowClient(ns ...string) v1alpha1.WorkflowInterface { log.Fatal(err) } } - wfcs := wfclientset.NewForConfigOrDie(restConfig) - wfClient = wfcs.ArgoprojV1alpha1().Workflows(namespace) + wfClientset = wfclientset.NewForConfigOrDie(restConfig) + wfClient = wfClientset.ArgoprojV1alpha1().Workflows(namespace) return wfClient } From c341a8653f5e6edaa0354d709d1d425b4254517c Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Sat, 27 Jul 2019 00:49:27 +0200 Subject: [PATCH 04/15] Adapt the call to the changed SubmitWorkflow --- cmd/argo/commands/resubmit.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/argo/commands/resubmit.go b/cmd/argo/commands/resubmit.go index b5243723de6b..5f91a0b5754d 100644 --- a/cmd/argo/commands/resubmit.go +++ b/cmd/argo/commands/resubmit.go @@ -1,6 +1,7 @@ package commands import ( + "log" "os" "github.com/argoproj/argo/workflow/util" @@ -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, newWF, nil) + created, err := util.SubmitWorkflow(wfClient, wfClientset, namespace, newWF, nil) errors.CheckError(err) printWorkflow(created, cliSubmitOpts.output, DefaultStatus) waitOrWatch([]string{created.Name}, cliSubmitOpts) From e32578cba39d0396cea11dc9421872306af00935 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Sat, 27 Jul 2019 01:25:57 +0200 Subject: [PATCH 05/15] Lint the code --- cmd/argo/commands/submit.go | 4 ++-- workflow/artifacts/raw/raw_test.go | 7 ++++--- workflow/controller/controller_test.go | 3 ++- workflow/controller/operator_test.go | 3 ++- workflow/util/util.go | 4 ++-- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index 35ce5c940672..a9fb27b19f5a 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -118,7 +118,7 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c } } - if submitOpts.DryRun{ + if submitOpts.DryRun { if cliOpts.watch { log.Fatalf("--watch cannot be combined with --dry-run") } @@ -136,7 +136,7 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c if err != nil { log.Fatal(err) } - + var workflowNames []string for _, wf := range workflows { diff --git a/workflow/artifacts/raw/raw_test.go b/workflow/artifacts/raw/raw_test.go index a846d7633124..e77506f80495 100644 --- a/workflow/artifacts/raw/raw_test.go +++ b/workflow/artifacts/raw/raw_test.go @@ -1,13 +1,14 @@ package raw_test import ( - wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" - "github.com/argoproj/argo/workflow/artifacts/raw" - "github.com/stretchr/testify/assert" "io/ioutil" "os" "testing" "time" + + wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" + "github.com/argoproj/argo/workflow/artifacts/raw" + "github.com/stretchr/testify/assert" ) const ( diff --git a/workflow/controller/controller_test.go b/workflow/controller/controller_test.go index e948f747d6d5..684d1ff0fa56 100644 --- a/workflow/controller/controller_test.go +++ b/workflow/controller/controller_test.go @@ -3,11 +3,12 @@ package controller import ( "bytes" "encoding/json" - "github.com/argoproj/argo/workflow/config" "io" "io/ioutil" "testing" + "github.com/argoproj/argo/workflow/config" + wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" fakewfclientset "github.com/argoproj/argo/pkg/client/clientset/versioned/fake" "github.com/ghodss/yaml" diff --git a/workflow/controller/operator_test.go b/workflow/controller/operator_test.go index 93fc55d74de3..8ff6ee9102e7 100644 --- a/workflow/controller/operator_test.go +++ b/workflow/controller/operator_test.go @@ -3,10 +3,11 @@ package controller import ( "encoding/json" "fmt" - "github.com/argoproj/argo/workflow/config" "strings" "testing" + "github.com/argoproj/argo/workflow/config" + wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" "github.com/argoproj/argo/test" "github.com/argoproj/argo/workflow/common" diff --git a/workflow/util/util.go b/workflow/util/util.go index d7d73dc98d1e..663aade2e49a 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -142,7 +142,7 @@ type SubmitOpts struct { Parameters []string // --parameter ParameterFile string // --parameter-file ServiceAccount string // --serviceaccount - DryRun bool // --dry-run + DryRun bool // --dry-run OwnerReference *metav1.OwnerReference // useful if your custom controller creates argo workflow resources } @@ -246,7 +246,7 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int if err != nil { return nil, err } - if opts.DryRun { + if opts.DryRun { // Keep the workflow metadata because it will be removed by the Post request workflowTypeMeta := wf.TypeMeta err := wfClientset.ArgoprojV1alpha1().RESTClient().Post(). From 60ece2845876c98e014be89de33490253b02aacf Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Mon, 29 Jul 2019 20:37:15 +0200 Subject: [PATCH 06/15] Get the namespace from the workflow when possible --- cmd/argo/commands/resubmit.go | 8 +------- cmd/argo/commands/submit.go | 16 +++++++++------- workflow/util/util.go | 4 ++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/cmd/argo/commands/resubmit.go b/cmd/argo/commands/resubmit.go index 5f91a0b5754d..d837e259f00d 100644 --- a/cmd/argo/commands/resubmit.go +++ b/cmd/argo/commands/resubmit.go @@ -1,7 +1,6 @@ package commands import ( - "log" "os" "github.com/argoproj/argo/workflow/util" @@ -24,17 +23,12 @@ 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, namespace, newWF, nil) + created, err := util.SubmitWorkflow(wfClient, wfClientset, newWF, nil) errors.CheckError(err) printWorkflow(created, cliSubmitOpts.output, DefaultStatus) waitOrWatch([]string{created.Name}, cliSubmitOpts) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index a9fb27b19f5a..b5f82633ea0d 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -132,11 +132,6 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c os.Exit(1) } - namespace, _, err := clientConfig.Namespace() - if err != nil { - log.Fatal(err) - } - var workflowNames []string for _, wf := range workflows { @@ -144,8 +139,15 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c wfClient := defaultWFClient if wf.Namespace != "" { wfClient = InitWorkflowClient(wf.Namespace) - } - created, err := util.SubmitWorkflow(wfClient, wfClientset, namespace, &wf, submitOpts) + } /*else { + // This is here to avoid passing an empty namespace when using --dry-run + namespace, _, err := clientConfig.Namespace() + if err != nil { + log.Fatal(err) + } + wf.Namespace = namespace + }*/ + created, err := util.SubmitWorkflow(wfClient, wfClientset, &wf, submitOpts) if err != nil { log.Fatalf("Failed to submit workflow: %v", err) } diff --git a/workflow/util/util.go b/workflow/util/util.go index 663aade2e49a..3ff9a7b5955e 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -147,7 +147,7 @@ type SubmitOpts struct { } // SubmitWorkflow validates and submit a single workflow and override some of the fields of the workflow -func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Interface, namespace string, wf *wfv1.Workflow, opts *SubmitOpts) (*wfv1.Workflow, error) { +func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Interface, wf *wfv1.Workflow, opts *SubmitOpts) (*wfv1.Workflow, error) { if opts == nil { opts = &SubmitOpts{} } @@ -250,7 +250,7 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int // Keep the workflow metadata because it will be removed by the Post request workflowTypeMeta := wf.TypeMeta err := wfClientset.ArgoprojV1alpha1().RESTClient().Post(). - Namespace(namespace). + Namespace(wf.Namespace). Resource("workflows"). Body(wf). Param("dryRun", "All"). From cb78bda0fa8ae5e1fba95aa1aaf3ac2f9b95a364 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Mon, 29 Jul 2019 20:43:05 +0200 Subject: [PATCH 07/15] Uncomment block of code This was commented out for debugging purposes --- cmd/argo/commands/submit.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index b5f82633ea0d..0f9a1e09fbed 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -139,14 +139,14 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c wfClient := defaultWFClient if wf.Namespace != "" { wfClient = InitWorkflowClient(wf.Namespace) - } /*else { + } else { // This is here to avoid passing an empty namespace when using --dry-run namespace, _, err := clientConfig.Namespace() if err != nil { log.Fatal(err) } wf.Namespace = namespace - }*/ + } created, err := util.SubmitWorkflow(wfClient, wfClientset, &wf, submitOpts) if err != nil { log.Fatalf("Failed to submit workflow: %v", err) From 7e97f0c630098c6af11a993fcb4effa4d4d613ef Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Tue, 30 Jul 2019 20:42:23 +0200 Subject: [PATCH 08/15] Add check for empty output format when using dry-run --- cmd/argo/commands/submit.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index 0f9a1e09fbed..b283ef9693fa 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -52,7 +52,7 @@ func NewSubmitCommand() *cobra.Command { command.Flags().StringArrayVarP(&submitOpts.Parameters, "parameter", "p", []string{}, "pass an input parameter") command.Flags().StringVar(&submitOpts.ServiceAccount, "serviceaccount", "", "run all pods in the workflow using specified serviceaccount") command.Flags().StringVar(&submitOpts.InstanceID, "instanceid", "", "submit with a specific controller's instance id label") - command.Flags().BoolVar(&submitOpts.DryRun, "dry-run", false, "display the declarative form without creating the flow") + command.Flags().BoolVar(&submitOpts.DryRun, "dry-run", false, "display the declarative form without creating the workflow") command.Flags().StringVarP(&cliSubmitOpts.output, "output", "o", "", "Output format. One of: name|json|yaml|wide") command.Flags().BoolVarP(&cliSubmitOpts.wait, "wait", "w", false, "wait for the workflow to complete") command.Flags().BoolVar(&cliSubmitOpts.watch, "watch", false, "watch the workflow until it completes") @@ -125,6 +125,9 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c if cliOpts.wait { log.Fatalf("--wait cannot be combined with --dry-run") } + if cliOpts.output == "" { + log.Fatalf("--dry-run should have an output option") + } } if len(workflows) == 0 { From c4dc0ad0e00542c02698b17b216bc45a0ac8bd65 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Tue, 30 Jul 2019 21:05:10 +0200 Subject: [PATCH 09/15] Create a separate CreateDryRun function This makes the code a bit more readable --- workflow/util/util.go | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/workflow/util/util.go b/workflow/util/util.go index 3ff9a7b5955e..b4aa97774c33 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -247,22 +247,31 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int return nil, err } if opts.DryRun { - // Keep the workflow metadata because it will be removed by the Post request - workflowTypeMeta := wf.TypeMeta - err := wfClientset.ArgoprojV1alpha1().RESTClient().Post(). - Namespace(wf.Namespace). - Resource("workflows"). - Body(wf). - Param("dryRun", "All"). - Do(). - Into(wf) - wf.TypeMeta = workflowTypeMeta + wf, err := CreateDryRun(wf, wfClientset) + if err != nil { + return nil, err + } return wf, err } else { return wfIf.Create(wf) } } +// CreateDryRun fills the workflow with the server's representation without creating it and returns an error, if there is any +func CreateDryRun(wf *wfv1.Workflow, wfClientset wfclientset.Interface) (*wfv1.Workflow, error) { + // Keep the workflow metadata because it will be overwritten by the Post request + workflowTypeMeta := wf.TypeMeta + err := wfClientset.ArgoprojV1alpha1().RESTClient().Post(). + Namespace(wf.Namespace). + Resource("workflows"). + Body(wf). + Param("dryRun", "All"). + Do(). + Into(wf) + wf.TypeMeta = workflowTypeMeta + return wf, err +} + // SuspendWorkflow suspends a workflow by setting spec.suspend to true. Retries conflict errors func SuspendWorkflow(wfIf v1alpha1.WorkflowInterface, workflowName string) error { err := wait.ExponentialBackoff(retry.DefaultRetry, func() (bool, error) { From 85472099afff20942d5f51f47c3cdeba21b88206 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Wed, 31 Jul 2019 21:17:32 +0200 Subject: [PATCH 10/15] Change dry-run to server-dry-run --- cmd/argo/commands/submit.go | 12 ++++++------ workflow/util/util.go | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index b283ef9693fa..c5bfd0533c12 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -52,7 +52,7 @@ func NewSubmitCommand() *cobra.Command { command.Flags().StringArrayVarP(&submitOpts.Parameters, "parameter", "p", []string{}, "pass an input parameter") command.Flags().StringVar(&submitOpts.ServiceAccount, "serviceaccount", "", "run all pods in the workflow using specified serviceaccount") command.Flags().StringVar(&submitOpts.InstanceID, "instanceid", "", "submit with a specific controller's instance id label") - command.Flags().BoolVar(&submitOpts.DryRun, "dry-run", false, "display the declarative form without creating the workflow") + command.Flags().BoolVar(&submitOpts.ServerDryRun, "server-dry-run", false, "send request to server with dry-run flag which will modify the workflow without creating it") command.Flags().StringVarP(&cliSubmitOpts.output, "output", "o", "", "Output format. One of: name|json|yaml|wide") command.Flags().BoolVarP(&cliSubmitOpts.wait, "wait", "w", false, "wait for the workflow to complete") command.Flags().BoolVar(&cliSubmitOpts.watch, "watch", false, "watch the workflow until it completes") @@ -118,15 +118,15 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c } } - if submitOpts.DryRun { + if submitOpts.ServerDryRun { if cliOpts.watch { - log.Fatalf("--watch cannot be combined with --dry-run") + log.Fatalf("--watch cannot be combined with --server-dry-run") } if cliOpts.wait { - log.Fatalf("--wait cannot be combined with --dry-run") + log.Fatalf("--wait cannot be combined with --server-dry-run") } if cliOpts.output == "" { - log.Fatalf("--dry-run should have an output option") + log.Fatalf("--server-dry-run should have an output option") } } @@ -143,7 +143,7 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c if wf.Namespace != "" { wfClient = InitWorkflowClient(wf.Namespace) } else { - // This is here to avoid passing an empty namespace when using --dry-run + // This is here to avoid passing an empty namespace when using --server-dry-run namespace, _, err := clientConfig.Namespace() if err != nil { log.Fatal(err) diff --git a/workflow/util/util.go b/workflow/util/util.go index b4aa97774c33..601dd3ebf7d5 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -142,7 +142,7 @@ type SubmitOpts struct { Parameters []string // --parameter ParameterFile string // --parameter-file ServiceAccount string // --serviceaccount - DryRun bool // --dry-run + ServerDryRun bool // --server-dry-run OwnerReference *metav1.OwnerReference // useful if your custom controller creates argo workflow resources } @@ -246,8 +246,8 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int if err != nil { return nil, err } - if opts.DryRun { - wf, err := CreateDryRun(wf, wfClientset) + if opts.ServerDryRun { + wf, err := CreateServerDryRun(wf, wfClientset) if err != nil { return nil, err } @@ -257,8 +257,8 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int } } -// CreateDryRun fills the workflow with the server's representation without creating it and returns an error, if there is any -func CreateDryRun(wf *wfv1.Workflow, wfClientset wfclientset.Interface) (*wfv1.Workflow, error) { +// CreateServerDryRun fills the workflow struct with the server's representation without creating it and returns an error, if there is any +func CreateServerDryRun(wf *wfv1.Workflow, wfClientset wfclientset.Interface) (*wfv1.Workflow, error) { // Keep the workflow metadata because it will be overwritten by the Post request workflowTypeMeta := wf.TypeMeta err := wfClientset.ArgoprojV1alpha1().RESTClient().Post(). From 5f1680bc27be0beee8d6c4fe3995d629974ced50 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Wed, 31 Jul 2019 23:10:12 +0200 Subject: [PATCH 11/15] Add a check for the server api version when using server-dry-run --- cmd/argo/commands/submit.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index c5bfd0533c12..a592f4367108 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -6,10 +6,13 @@ import ( "log" "net/http" "os" + "strconv" "github.com/argoproj/pkg/json" "github.com/spf13/cobra" + apimachineryversion "k8s.io/apimachinery/pkg/version" + wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" cmdutil "github.com/argoproj/argo/util/cmd" "github.com/argoproj/argo/workflow/common" @@ -128,6 +131,17 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c if cliOpts.output == "" { log.Fatalf("--server-dry-run should have an output option") } + serverVersion, err := wfClientset.Discovery().ServerVersion() + if err != nil { + log.Fatalf("Unexpected error while getting the server's api version") + } + isCompatible, err := checkServerVersionForDryRun(serverVersion) + if err != nil { + log.Fatalf("Unexpected error while checking the server's api version compatibility with --server-dry-run") + } + if !isCompatible { + log.Fatalf("--server-dry-run is not available for server api versions older than v1.12") + } } if len(workflows) == 0 { @@ -160,6 +174,24 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c waitOrWatch(workflowNames, *cliOpts) } +// Checks whether the server has support for the dry-run option +func checkServerVersionForDryRun(serverVersion *apimachineryversion.Info) (bool, error) { + majorVersion, err := strconv.Atoi(serverVersion.Major) + if err != nil { + return false, err + } + minorVersion, err := strconv.Atoi(serverVersion.Minor) + if err != nil { + return false, err + } + if majorVersion < 1 { + return false, nil + } else if majorVersion == 1 && minorVersion < 12 { + return false, nil + } + return true, nil +} + // unmarshalWorkflows unmarshals the input bytes as either json or yaml func unmarshalWorkflows(wfBytes []byte, strict bool) []wfv1.Workflow { var wf wfv1.Workflow From 8dc167d8461ebadce55653a01d9882918e7db459 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Thu, 1 Aug 2019 00:41:32 +0200 Subject: [PATCH 12/15] Add a client-side dry-run option --- cmd/argo/commands/submit.go | 24 ++++++++++++++++++++---- workflow/util/util.go | 13 +++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index a592f4367108..2bb37b94b22c 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -55,6 +55,7 @@ func NewSubmitCommand() *cobra.Command { command.Flags().StringArrayVarP(&submitOpts.Parameters, "parameter", "p", []string{}, "pass an input parameter") command.Flags().StringVar(&submitOpts.ServiceAccount, "serviceaccount", "", "run all pods in the workflow using specified serviceaccount") command.Flags().StringVar(&submitOpts.InstanceID, "instanceid", "", "submit with a specific controller's instance id label") + command.Flags().BoolVar(&submitOpts.DryRun, "dry-run", false, "modify the workflow on the client-side without creating it") command.Flags().BoolVar(&submitOpts.ServerDryRun, "server-dry-run", false, "send request to server with dry-run flag which will modify the workflow without creating it") command.Flags().StringVarP(&cliSubmitOpts.output, "output", "o", "", "Output format. One of: name|json|yaml|wide") command.Flags().BoolVarP(&cliSubmitOpts.wait, "wait", "w", false, "wait for the workflow to complete") @@ -119,15 +120,30 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c if cliOpts.wait { log.Fatalf("--wait cannot be combined with --watch") } + if submitOpts.DryRun { + log.Fatalf("--watch cannot be combined with --dry-run") + } + if submitOpts.ServerDryRun { + log.Fatalf("--watch cannot be combined with --server-dry-run") + } } - if submitOpts.ServerDryRun { - if cliOpts.watch { - log.Fatalf("--watch cannot be combined with --server-dry-run") + if cliOpts.wait { + if submitOpts.DryRun { + log.Fatalf("--wait cannot be combined with --dry-run") } - if cliOpts.wait { + if submitOpts.ServerDryRun { log.Fatalf("--wait cannot be combined with --server-dry-run") } + } + + if submitOpts.DryRun { + if cliOpts.output == "" { + log.Fatalf("--dry-run should have an output option") + } + } + + if submitOpts.ServerDryRun { if cliOpts.output == "" { log.Fatalf("--server-dry-run should have an output option") } diff --git a/workflow/util/util.go b/workflow/util/util.go index 601dd3ebf7d5..334bccec6954 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -28,6 +28,8 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/utils/pointer" + "k8s.io/apiserver/pkg/storage/names" + "github.com/argoproj/argo/errors" "github.com/argoproj/argo/pkg/apis/workflow" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" @@ -142,6 +144,7 @@ type SubmitOpts struct { Parameters []string // --parameter ParameterFile string // --parameter-file ServiceAccount string // --serviceaccount + DryRun bool // --dry-run ServerDryRun bool // --server-dry-run OwnerReference *metav1.OwnerReference // useful if your custom controller creates argo workflow resources } @@ -246,12 +249,22 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int if err != nil { return nil, err } + + if wf.ObjectMeta.Name == "" && wf.ObjectMeta.GenerateName == "" { + log.Fatalf("name and generateName cannot be both empty") + } + if opts.ServerDryRun { wf, err := CreateServerDryRun(wf, wfClientset) if err != nil { return nil, err } return wf, err + } else if opts.DryRun { + if wf.ObjectMeta.Name == "" { + wf.ObjectMeta.Name = names.SimpleNameGenerator.GenerateName(wf.ObjectMeta.GenerateName) + } + return wf, nil } else { return wfIf.Create(wf) } From f1eec3788eb384bab415be50ce2325fd0747cd44 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Thu, 1 Aug 2019 07:12:43 +0200 Subject: [PATCH 13/15] Remove name generation for client-side dry-run --- workflow/util/util.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/workflow/util/util.go b/workflow/util/util.go index 334bccec6954..f5b5a7f37fc4 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -28,8 +28,6 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/utils/pointer" - "k8s.io/apiserver/pkg/storage/names" - "github.com/argoproj/argo/errors" "github.com/argoproj/argo/pkg/apis/workflow" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" @@ -250,10 +248,6 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int return nil, err } - if wf.ObjectMeta.Name == "" && wf.ObjectMeta.GenerateName == "" { - log.Fatalf("name and generateName cannot be both empty") - } - if opts.ServerDryRun { wf, err := CreateServerDryRun(wf, wfClientset) if err != nil { @@ -261,9 +255,6 @@ func SubmitWorkflow(wfIf v1alpha1.WorkflowInterface, wfClientset wfclientset.Int } return wf, err } else if opts.DryRun { - if wf.ObjectMeta.Name == "" { - wf.ObjectMeta.Name = names.SimpleNameGenerator.GenerateName(wf.ObjectMeta.GenerateName) - } return wf, nil } else { return wfIf.Create(wf) From 4acc29bb92da6e17610115d179e14617bffd4797 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Thu, 1 Aug 2019 21:24:36 +0200 Subject: [PATCH 14/15] Prevent combining dry-run with server-dry-run --- cmd/argo/commands/submit.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/argo/commands/submit.go b/cmd/argo/commands/submit.go index 2bb37b94b22c..6e97c7ef6bc5 100644 --- a/cmd/argo/commands/submit.go +++ b/cmd/argo/commands/submit.go @@ -141,6 +141,9 @@ func SubmitWorkflows(filePaths []string, submitOpts *util.SubmitOpts, cliOpts *c if cliOpts.output == "" { log.Fatalf("--dry-run should have an output option") } + if submitOpts.ServerDryRun { + log.Fatalf("--dry-run cannot be combined with --server-dry-run") + } } if submitOpts.ServerDryRun { From dd613b3ac1fa3e5c151dba0105338bca132493c9 Mon Sep 17 00:00:00 2001 From: AnesBenmerzoug Date: Fri, 2 Aug 2019 18:06:59 +0200 Subject: [PATCH 15/15] Add a comment to describe the wfClientset variable --- cmd/argo/commands/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argo/commands/common.go b/cmd/argo/commands/common.go index fed9399144d9..a687243578cb 100644 --- a/cmd/argo/commands/common.go +++ b/cmd/argo/commands/common.go @@ -21,7 +21,7 @@ var ( restConfig *rest.Config clientConfig clientcmd.ClientConfig clientset *kubernetes.Clientset - wfClientset *wfclientset.Clientset + wfClientset *wfclientset.Clientset // wfClientset is used for the server-dry-run submit option wfClient v1alpha1.WorkflowInterface jobStatusIconMap map[wfv1.NodePhase]string noColor bool