Browse Source

完成重构

yjp 9 months ago
parent
commit
d831ff9fd1
5 changed files with 798 additions and 1200 deletions
  1. 3 0
      client/client.go
  2. 290 642
      client/workflow.go
  3. 4 4
      test/common.go
  4. 9 9
      test/workflow_template_test.go
  5. 492 545
      test/workflow_test.go

+ 3 - 0
client/client.go

@@ -3,6 +3,7 @@ package client
 import (
 	"context"
 	"github.com/argoproj/argo-workflows/v3/pkg/apiclient"
+	"github.com/argoproj/argo-workflows/v3/pkg/apiclient/workflow"
 	"github.com/argoproj/argo-workflows/v3/pkg/apiclient/workflowtemplate"
 	"github.com/pkg/errors"
 	"k8s.io/client-go/tools/clientcmd"
@@ -13,6 +14,7 @@ type Client struct {
 	ctx                     context.Context
 	client                  apiclient.Client
 	workflowTemplateService workflowtemplate.WorkflowTemplateServiceClient
+	workflowService         workflow.WorkflowServiceClient
 }
 
 func NewClient(kubeConfigEnv string) (*Client, error) {
@@ -41,5 +43,6 @@ func NewClient(kubeConfigEnv string) (*Client, error) {
 		ctx:                     apiClientCtx,
 		client:                  apiClient,
 		workflowTemplateService: workflowTemplateService,
+		workflowService:         apiClient.NewWorkflowServiceClient(),
 	}, nil
 }

+ 290 - 642
client/workflow.go

@@ -1,646 +1,294 @@
 package client
 
-const (
-	createWorkflowRelativeUrl          = "/api/v1/workflows/{namespace}"
-	deleteWorkflowRelativeUrl          = "/api/v1/workflows/{namespace}/{name}"
-	getWorkflowsInNamespaceRelativeUrl = "/api/v1/workflows/{namespace}"
-	getWorkflowRelativeUrl             = "/api/v1/workflows/{namespace}/{name}"
-	lintWorkflowRelativeUrl            = "/api/v1/workflows/{namespace}/lint"
-	submitWorkflowRelativeUrl          = "/api/v1/workflows/{namespace}/submit"
-	resubmitWorkflowRelativeUrl        = "/api/v1/workflows/{namespace}/{name}/resubmit"
-	retryWorkflowRelativeUrl           = "/api/v1/workflows/{namespace}/{name}/retry"
-	stopWorkflowRelativeUrl            = "/api/v1/workflows/{namespace}/{name}/stop"
-	terminateWorkflowRelativeUrl       = "/api/v1/workflows/{namespace}/{name}/terminate"
-	setWorkflowRelativeUrl             = "/api/v1/workflows/{namespace}/{name}/set"
-	suspendWorkflowRelativeUrl         = "/api/v1/workflows/{namespace}/{name}/suspend"
-	resumeWorkflowRelativeUrl          = "/api/v1/workflows/{namespace}/{name}/resume"
-	getWorkflowEventsStreamRelativeUrl = "/api/v1/workflow-events/{namespace}"
+import (
+	"github.com/argoproj/argo-workflows/v3/pkg/apiclient/workflow"
+	"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
+	"github.com/pkg/errors"
 )
 
-//
-//type CreateWorkflowParams struct {
-//	Namespace          string
-//	WorkflowDefinition map[string]any
-//}
-//
-//// CreateWorkflow 创建工作流
-//func (c *Client) CreateWorkflow(params CreateWorkflowParams) (string, error) {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace": params.Namespace,
-//			"workflow":  params.WorkflowDefinition,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Post(createWorkflowRelativeUrl)
-//	if err != nil {
-//		return "", errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		metadata, ok := responseMap["metadata"]
-//		if !ok {
-//			return "", errors.New("metadata为空")
-//		}
-//
-//		metadataMap, ok := metadata.(map[string]any)
-//		if !ok {
-//			return "", errors.New("metadata不是map")
-//		}
-//
-//		workflowName, ok := metadataMap["name"]
-//		if !ok {
-//			return "", errors.New("metadata中没有工作流名称")
-//		}
-//
-//		workflowNameStr, ok := workflowName.(string)
-//		if !ok {
-//			return "", errors.New("工作流名称不是字符串")
-//		}
-//
-//		return workflowNameStr, nil
-//	case http.StatusConflict:
-//		return "", errors.New("工作流已存在")
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return "", errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return "", errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type DeleteWorkflowParams struct {
-//	Namespace string
-//	Name      string
-//}
-//
-//// DeleteWorkflow 删除工作流
-//func (c *Client) DeleteWorkflow(params DeleteWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Delete(deleteWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type GetWorkflowsInNamespaceParams struct {
-//	Namespace string
-//}
-//
-//// GetWorkflowsInNamespace 获取命名空间下的工作流
-//func (c *Client) GetWorkflowsInNamespace(params GetWorkflowsInNamespaceParams) ([]map[string]any, error) {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Get(getWorkflowsInNamespaceRelativeUrl)
-//	if err != nil {
-//		return nil, errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		itemsValue, ok := responseMap["items"]
-//		if !ok {
-//			return nil, errors.New("没有获取到items参数")
-//		}
-//
-//		items, ok := itemsValue.([]any)
-//		if !ok {
-//			return nil, errors.New("items不是slice")
-//		}
-//
-//		templateDefinitions := make([]map[string]any, len(items))
-//		for i, item := range items {
-//			templateDefinition, ok := item.(map[string]any)
-//			if !ok {
-//				return nil, errors.New("item无法转换为map[string]any")
-//			}
-//
-//			templateDefinitions[i] = templateDefinition
-//		}
-//
-//		return templateDefinitions, nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return nil, errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return nil, errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type GetWorkflowParams struct {
-//	Namespace string
-//	Name      string
-//}
-//
-//// GetWorkflow 获取指定的工作流
-//func (c *Client) GetWorkflow(params GetWorkflowParams) (map[string]any, error) {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Get(getWorkflowRelativeUrl)
-//	if err != nil {
-//		return nil, errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return responseMap, nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return nil, errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return nil, errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type LintWorkflowParams struct {
-//	Namespace          string
-//	WorkflowDefinition map[string]any
-//}
-//
-//// LintWorkflow 检查工作流定义语法
-//func (c *Client) LintWorkflow(params LintWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace": params.Namespace,
-//			"workflow":  params.WorkflowDefinition,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Post(lintWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type SubmitWorkflowFromWorkflowTemplateParams struct {
-//	Namespace    string
-//	TemplateName string
-//	Parameters   []string
-//}
-//
-//// SubmitWorkflowFromWorkflowTemplate 基于工作流模板提交工作流
-//func (c *Client) SubmitWorkflowFromWorkflowTemplate(params SubmitWorkflowFromWorkflowTemplateParams) (string, error) {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace":    params.Namespace,
-//			"resourceKind": "WorkflowTemplate",
-//			"resourceName": params.TemplateName,
-//			"submitOptions": map[string]any{
-//				"parameters": params.Parameters,
-//			},
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Post(submitWorkflowRelativeUrl)
-//	if err != nil {
-//		return "", errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		metadata, ok := responseMap["metadata"]
-//		if !ok {
-//			return "", errors.New("metadata为空")
-//		}
-//
-//		metadataMap, ok := metadata.(map[string]any)
-//		if !ok {
-//			return "", errors.New("metadata不是map")
-//		}
-//
-//		workflowName, ok := metadataMap["name"]
-//		if !ok {
-//			return "", errors.New("metadata中没有工作流名称")
-//		}
-//
-//		workflowNameStr, ok := workflowName.(string)
-//		if !ok {
-//			return "", errors.New("工作流名称不是字符串")
-//		}
-//
-//		return workflowNameStr, nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return "", errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return "", errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type ResubmitWorkflowParams struct {
-//	Namespace          string
-//	Name               string
-//	Memoized           bool
-//	ResubmitParameters []string
-//}
-//
-//// ResubmitWorkflow 重提交工作流
-//// 有三种方式可以用来重复提交(可以结合使用):重新运行,基于缓存的和传递重提交参数
-//// 基于缓存的必须在Error和Failed的工作流上才可以使用
-//func (c *Client) ResubmitWorkflow(params ResubmitWorkflowParams) (string, error) {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace":  params.Namespace,
-//			"name":       params.Name,
-//			"memoized":   params.Memoized,
-//			"parameters": params.ResubmitParameters,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Put(resubmitWorkflowRelativeUrl)
-//	if err != nil {
-//		return "", errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		metadata, ok := responseMap["metadata"]
-//		if !ok {
-//			return "", errors.New("metadata为空")
-//		}
-//
-//		metadataMap, ok := metadata.(map[string]any)
-//		if !ok {
-//			return "", errors.New("metadata不是map")
-//		}
-//
-//		workflowName, ok := metadataMap["name"]
-//		if !ok {
-//			return "", errors.New("metadata中没有工作流名称")
-//		}
-//
-//		workflowNameStr, ok := workflowName.(string)
-//		if !ok {
-//			return "", errors.New("工作流名称不是字符串")
-//		}
-//
-//		return workflowNameStr, nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return "", errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return "", errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type RetryWorkflowParams struct {
-//	Namespace                      string
-//	Name                           string
-//	RetryParameters                []string
-//	RetryOnSuccessfulWorkflow      bool
-//	RetryWorkflowNodeFieldSelector string
-//}
-//
-//// RetryWorkflow 重新运行工作流(默认只能失败的工作流上重新运行)
-//func (c *Client) RetryWorkflow(params RetryWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace":         params.Namespace,
-//			"name":              params.Name,
-//			"parameters":        params.RetryParameters,
-//			"restartSuccessful": params.RetryOnSuccessfulWorkflow,
-//			"nodeFieldSelector": params.RetryWorkflowNodeFieldSelector,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Put(retryWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type StopWorkflowParams struct {
-//	Namespace         string
-//	Name              string
-//	NodeFieldSelector string
-//	Message           string
-//}
-//
-//// StopWorkflow 终止工作流运行,会调用所有的退出处理器
-//func (c *Client) StopWorkflow(params StopWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace":         params.Namespace,
-//			"name":              params.Name,
-//			"nodeFieldSelector": params.NodeFieldSelector,
-//			"message":           params.Message,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Put(stopWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type TerminateWorkflowParams struct {
-//	Namespace string
-//	Name      string
-//}
-//
-//// TerminateWorkflow 终止工作流运行,不调用所有的退出处理器
-//func (c *Client) TerminateWorkflow(params TerminateWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Put(terminateWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type SetWorkflowParams struct {
-//	Namespace         string
-//	Name              string
-//	NodeFieldSelector string
-//	OutputParameters  string
-//	Message           string
-//	Phase             string
-//}
-//
-//// SetWorkflow 设置工作流的参数
-//func (c *Client) SetWorkflow(params SetWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace":         params.Namespace,
-//			"name":              params.Name,
-//			"nodeFieldSelector": params.NodeFieldSelector,
-//			"outputParameters":  params.OutputParameters,
-//			"message":           params.Message,
-//			"phase":             params.Phase,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Put(setWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type SuspendWorkflowParams struct {
-//	Namespace string
-//	Name      string
-//}
-//
-//// SuspendWorkflow 挂起工作流
-//func (c *Client) SuspendWorkflow(params SuspendWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Put(suspendWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type ResumeWorkflowParams struct {
-//	Namespace         string
-//	Name              string
-//	NodeFieldSelector string
-//}
-//
-//// ResumeWorkflow 恢复被挂起的工作流
-//func (c *Client) ResumeWorkflow(params ResumeWorkflowParams) error {
-//	responseMap := make(map[string]any)
-//
-//	resp, err := c.restyClient.R().
-//		SetHeader("Content-Type", "application/json").
-//		SetAuthToken(c.token).
-//		SetPathParams(map[string]string{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetBody(map[string]any{
-//			"namespace": params.Namespace,
-//			"name":      params.Name,
-//		}).
-//		SetResult(&responseMap).
-//		SetError(&responseMap).
-//		Put(resumeWorkflowRelativeUrl)
-//	if err != nil {
-//		return errors.New(err.Error())
-//	}
-//
-//	switch resp.StatusCode() {
-//	case http.StatusOK:
-//		return nil
-//	default:
-//		message, ok := responseMap["message"]
-//		if !ok {
-//			return errors.Errorf("%v", resp.Status())
-//		}
-//
-//		return errors.Errorf("%v, %v", resp.Status(), message)
-//	}
-//}
-//
-//type EventCallback func(event map[string]any, eventErr error) error
-//
-//type GetWorkflowEventsStreamParams struct {
-//	Namespace string
-//	Name      string
-//}
-//
-//// GetWorkflowEventsStream 监听工作流事件
-//func (c *Client) GetWorkflowEventsStream(params GetWorkflowEventsStreamParams, callback EventCallback) error {
-//	return nil
-//}
+type CreateWorkflowParams struct {
+	Namespace          string
+	WorkflowDefinition string
+}
+
+// CreateWorkflow 创建工作流
+func (c *Client) CreateWorkflow(params CreateWorkflowParams) (string, error) {
+	wf := new(v1alpha1.Workflow)
+	err := unmarshalYamlToJsonStruct([]byte(params.WorkflowDefinition), wf)
+	if err != nil {
+		return "", err
+	}
+
+	response, err := c.workflowService.CreateWorkflow(c.ctx, &workflow.WorkflowCreateRequest{
+		Namespace: params.Namespace,
+		Workflow:  wf,
+	})
+	if err != nil {
+		return "", errors.New(err.Error())
+	}
+
+	return response.Name, nil
+}
+
+type DeleteWorkflowParams struct {
+	Namespace string
+	Name      string
+}
+
+// DeleteWorkflow 删除工作流
+func (c *Client) DeleteWorkflow(params DeleteWorkflowParams) error {
+	_, err := c.workflowService.DeleteWorkflow(c.ctx, &workflow.WorkflowDeleteRequest{
+		Namespace: params.Namespace,
+		Name:      params.Name,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type GetWorkflowsInNamespaceParams struct {
+	Namespace string
+}
+
+// GetWorkflowsInNamespace 获取命名空间下的工作流
+func (c *Client) GetWorkflowsInNamespace(params GetWorkflowsInNamespaceParams) (v1alpha1.Workflows, error) {
+	response, err := c.workflowService.ListWorkflows(c.ctx, &workflow.WorkflowListRequest{
+		Namespace: params.Namespace,
+	})
+	if err != nil {
+		return nil, errors.New(err.Error())
+	}
+
+	return response.Items, nil
+}
+
+type GetWorkflowParams struct {
+	Namespace string
+	Name      string
+}
+
+// GetWorkflow 获取指定的工作流
+func (c *Client) GetWorkflow(params GetWorkflowParams) (*v1alpha1.Workflow, error) {
+	response, err := c.workflowService.GetWorkflow(c.ctx, &workflow.WorkflowGetRequest{
+		Namespace: params.Namespace,
+		Name:      params.Name,
+	})
+	if err != nil {
+		return nil, errors.New(err.Error())
+	}
+
+	return response, nil
+}
+
+type LintWorkflowParams struct {
+	Namespace          string
+	WorkflowDefinition string
+}
+
+// LintWorkflow 检查工作流定义语法
+func (c *Client) LintWorkflow(params LintWorkflowParams) error {
+	wf := new(v1alpha1.Workflow)
+	err := unmarshalYamlToJsonStruct([]byte(params.WorkflowDefinition), wf)
+	if err != nil {
+		return err
+	}
+
+	_, err = c.workflowService.LintWorkflow(c.ctx, &workflow.WorkflowLintRequest{
+		Namespace: params.Namespace,
+		Workflow:  wf,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type SubmitWorkflowFromWorkflowTemplateParams struct {
+	Namespace    string
+	TemplateName string
+	Parameters   []string
+}
+
+// SubmitWorkflowFromWorkflowTemplate 基于工作流模板提交工作流
+func (c *Client) SubmitWorkflowFromWorkflowTemplate(params SubmitWorkflowFromWorkflowTemplateParams) (string, error) {
+	response, err := c.workflowService.SubmitWorkflow(c.ctx, &workflow.WorkflowSubmitRequest{
+		Namespace:    params.Namespace,
+		ResourceKind: "WorkflowTemplate",
+		ResourceName: params.TemplateName,
+		SubmitOptions: &v1alpha1.SubmitOpts{
+			Parameters: params.Parameters,
+		},
+	})
+	if err != nil {
+		return "", errors.New(err.Error())
+	}
+
+	return response.Name, nil
+}
+
+type ResubmitWorkflowParams struct {
+	Namespace          string
+	Name               string
+	Memoized           bool
+	ResubmitParameters []string
+}
+
+// ResubmitWorkflow 重提交工作流
+// 有三种方式可以用来重复提交(可以结合使用):重新运行,基于缓存的和传递重提交参数
+// 基于缓存的必须在Error和Failed的工作流上才可以使用
+func (c *Client) ResubmitWorkflow(params ResubmitWorkflowParams) (string, error) {
+	response, err := c.workflowService.ResubmitWorkflow(c.ctx, &workflow.WorkflowResubmitRequest{
+		Namespace:  params.Namespace,
+		Name:       params.Name,
+		Memoized:   params.Memoized,
+		Parameters: params.ResubmitParameters,
+	})
+	if err != nil {
+		return "", errors.New(err.Error())
+	}
+
+	return response.Name, nil
+}
+
+type RetryWorkflowParams struct {
+	Namespace                      string
+	Name                           string
+	RetryParameters                []string
+	RetrySuccessfulWorkflow        bool
+	RetryWorkflowNodeFieldSelector string
+}
+
+// RetryWorkflow 重新运行工作流(默认只能失败的工作流上重新运行)
+func (c *Client) RetryWorkflow(params RetryWorkflowParams) error {
+	_, err := c.workflowService.RetryWorkflow(c.ctx, &workflow.WorkflowRetryRequest{
+		Namespace:         params.Namespace,
+		Name:              params.Name,
+		RestartSuccessful: params.RetrySuccessfulWorkflow,
+		NodeFieldSelector: params.RetryWorkflowNodeFieldSelector,
+		Parameters:        params.RetryParameters,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type StopWorkflowParams struct {
+	Namespace         string
+	Name              string
+	NodeFieldSelector string
+	Message           string
+}
+
+// StopWorkflow 终止工作流运行,会调用所有的退出处理器
+func (c *Client) StopWorkflow(params StopWorkflowParams) error {
+	_, err := c.workflowService.StopWorkflow(c.ctx, &workflow.WorkflowStopRequest{
+		Namespace:         params.Namespace,
+		Name:              params.Name,
+		NodeFieldSelector: params.NodeFieldSelector,
+		Message:           params.Message,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type TerminateWorkflowParams struct {
+	Namespace string
+	Name      string
+}
+
+// TerminateWorkflow 终止工作流运行,不调用所有的退出处理器
+func (c *Client) TerminateWorkflow(params TerminateWorkflowParams) error {
+	_, err := c.workflowService.TerminateWorkflow(c.ctx, &workflow.WorkflowTerminateRequest{
+		Namespace: params.Namespace,
+		Name:      params.Name,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type SetWorkflowParams struct {
+	Namespace         string
+	Name              string
+	NodeFieldSelector string
+	OutputParameters  string
+	Message           string
+	Phase             string
+}
+
+// SetWorkflow 设置工作流的参数
+func (c *Client) SetWorkflow(params SetWorkflowParams) error {
+	_, err := c.workflowService.SetWorkflow(c.ctx, &workflow.WorkflowSetRequest{
+		Namespace:         params.Namespace,
+		Name:              params.Name,
+		NodeFieldSelector: params.NodeFieldSelector,
+		Message:           params.Message,
+		Phase:             params.Phase,
+		OutputParameters:  params.OutputParameters,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type SuspendWorkflowParams struct {
+	Namespace string
+	Name      string
+}
+
+// SuspendWorkflow 挂起工作流
+func (c *Client) SuspendWorkflow(params SuspendWorkflowParams) error {
+	_, err := c.workflowService.SuspendWorkflow(c.ctx, &workflow.WorkflowSuspendRequest{
+		Namespace: params.Namespace,
+		Name:      params.Name,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type ResumeWorkflowParams struct {
+	Namespace         string
+	Name              string
+	NodeFieldSelector string
+}
+
+// ResumeWorkflow 恢复被挂起的工作流
+func (c *Client) ResumeWorkflow(params ResumeWorkflowParams) error {
+	_, err := c.workflowService.ResumeWorkflow(c.ctx, &workflow.WorkflowResumeRequest{
+		Namespace:         params.Namespace,
+		Name:              params.Name,
+		NodeFieldSelector: params.NodeFieldSelector,
+	})
+	if err != nil {
+		return errors.New(err.Error())
+	}
+
+	return nil
+}
+
+type EventCallback func(event map[string]any, eventErr error) error
+
+type GetWorkflowEventsStreamParams struct {
+	Namespace string
+	Name      string
+}
+
+// GetWorkflowEventsStream 监听工作流事件
+func (c *Client) GetWorkflowEventsStream(params GetWorkflowEventsStreamParams, callback EventCallback) error {
+	return nil
+}

+ 4 - 4
test/common.go

@@ -8,10 +8,10 @@ import (
 )
 
 const (
-	kubeConfig = "/etc/rancher/k3s/k3s.yaml"
-
-	namespace            = "argo-api"
-	workflowTemplateName = "approve"
+	kubeConfig                     = "/etc/rancher/k3s/k3s.yaml"
+	namespace                      = "argo-api"
+	workflowTemplateName           = "approve"
+	workflowTemplateWithParamsName = "hello"
 )
 
 //go:embed definitions/approve_workflow_template.yaml

+ 9 - 9
test/workflow_template_test.go

@@ -41,18 +41,18 @@ func TestWorkflowTemplate(t *testing.T) {
 		}
 	}()
 
-	wfs, err := argo.GetInstance().GetWorkflowTemplatesInNamespace(client.GetWorkflowTemplatesInNamespaceParams{
+	wfts, err := argo.GetInstance().GetWorkflowTemplatesInNamespace(client.GetWorkflowTemplatesInNamespaceParams{
 		Namespace: namespace,
 	})
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	if len(wfs) != 1 {
-		t.Fatalf("%+v\n", errors.Errorf("数量不一致: %v", len(wfs)))
+	if len(wfts) != 1 {
+		t.Fatalf("%+v\n", errors.Errorf("数量不一致: %v", len(wfts)))
 	}
 
-	wf, err := argo.GetInstance().GetWorkflowTemplate(client.GetWorkflowTemplateParams{
+	wft, err := argo.GetInstance().GetWorkflowTemplate(client.GetWorkflowTemplateParams{
 		Namespace: namespace,
 		Name:      workflowTemplateName,
 	})
@@ -60,18 +60,18 @@ func TestWorkflowTemplate(t *testing.T) {
 		t.Fatalf("%+v\n", err)
 	}
 
-	if wf.Namespace != wfs[0].Namespace {
-		t.Fatalf("%+v\n", errors.Errorf("命名空间不一致: one: %s other: %s", wf.Namespace, wfs[0].Namespace))
+	if wft.Namespace != wfts[0].Namespace {
+		t.Fatalf("%+v\n", errors.Errorf("命名空间不一致: one: %s other: %s", wft.Namespace, wfts[0].Namespace))
 	}
 
-	if wf.Name != wfs[0].Name {
-		t.Fatalf("%+v\n", errors.Errorf("名称不一致: one: %s other: %s", wf.Name, wfs[0].Name))
+	if wft.Name != wfts[0].Name {
+		t.Fatalf("%+v\n", errors.Errorf("名称不一致: one: %s other: %s", wft.Name, wfts[0].Name))
 	}
 
 	err = argo.GetInstance().UpdateWorkflowTemplate(client.UpdateWorkflowTemplateParams{
 		Namespace:        namespace,
 		Name:             workflowTemplateName,
-		WorkflowTemplate: wf,
+		WorkflowTemplate: wft,
 	})
 	if err != nil {
 		t.Fatalf("%+v\n", err)

+ 492 - 545
test/workflow_test.go

@@ -1,547 +1,494 @@
 package test
 
-//
-//func TestWorkflowBase(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	workflowDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowYamlStr, &workflowDefinition)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	err = argo.GetInstance().LintWorkflow(client.LintWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	createdWorkflowDefinitions, err := argo.GetInstance().GetWorkflowsInNamespace(client.GetWorkflowsInNamespaceParams{
-//		Namespace: namespace,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	if len(createdWorkflowDefinitions) != 1 {
-//		t.Fatalf("%+v\n", errors.Errorf("数量不一致: %v", len(createdWorkflowDefinitions)))
-//	}
-//
-//	createdWorkflowDefinition, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	compareDefinitionMap(t, createdWorkflowDefinition, createdWorkflowDefinitions[0])
-//	compareDefinitionMap(t, createdWorkflowDefinitions[0], createdWorkflowDefinition)
-//}
-//
-//func TestSubmitWorkflow(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	templateDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowTemplateWithParamsYamlStr, &templateDefinition)
-//	if err != nil {
-//		panic(err)
-//	}
-//
-//	err = argo.GetInstance().CreateWorkflowTemplate(client.CreateWorkflowTemplateParams{
-//		Namespace:          namespace,
-//		TemplateDefinition: templateDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflowTemplate(client.DeleteWorkflowTemplateParams{
-//			Namespace: namespace,
-//			Name:      workflowTemplateWithParamsName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	submitWorkflowName, err := argo.GetInstance().SubmitWorkflowFromWorkflowTemplate(client.SubmitWorkflowFromWorkflowTemplateParams{
-//		Namespace:    namespace,
-//		TemplateName: workflowTemplateWithParamsName,
-//		Parameters:   []string{"message=Hello Submit"},
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      submitWorkflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	submittedWorkflowDefinition, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//		Namespace: namespace,
-//		Name:      submitWorkflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	specMap := submittedWorkflowDefinition["spec"].(map[string]any)
-//	argumentMap := specMap["arguments"].(map[string]any)
-//	parametersMap := argumentMap["parameters"].([]any)
-//
-//	if parametersMap[0].(map[string]any)["name"] != "message" {
-//		t.Fatalf("%+v\n", errors.Errorf("参数名称错误: %v", parametersMap[0].(map[string]any)["name"]))
-//	}
-//
-//	if parametersMap[0].(map[string]any)["value"] != "Hello Submit" {
-//		t.Fatalf("%+v\n", errors.Errorf("参数值错误: %v", parametersMap[0].(map[string]any)["value"]))
-//	}
-//}
-//
-//func TestResubmitWorkflow(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	workflowDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowYamlStr, &workflowDefinition)
-//	if err != nil {
-//		panic(err)
-//	}
-//
-//	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	resubmittedWorkflowName, err := argo.GetInstance().ResubmitWorkflow(client.ResubmitWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      resubmittedWorkflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//}
-//
-//func TestRetryWorkflow(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	workflowDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowYamlStr, &workflowDefinition)
-//	if err != nil {
-//		panic(err)
-//	}
-//
-//	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	err = argo.GetInstance().TerminateWorkflow(client.TerminateWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	for {
-//		currentWorkflowDefinitions, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//
-//		if currentWorkflowDefinitions["status"].(map[string]any)["phase"] != "Running" {
-//			break
-//		}
-//
-//		time.Sleep(1 * time.Second)
-//	}
-//
-//	err = argo.GetInstance().RetryWorkflow(client.RetryWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//}
-//
-//func TestStopWorkflow(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	workflowDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowYamlStr, &workflowDefinition)
-//	if err != nil {
-//		panic(err)
-//	}
-//
-//	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	err = argo.GetInstance().StopWorkflow(client.StopWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	for {
-//		currentWorkflowDefinitions, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//
-//		if currentWorkflowDefinitions["status"].(map[string]any)["phase"] != "Running" {
-//			break
-//		}
-//
-//		time.Sleep(1 * time.Second)
-//	}
-//}
-//
-//func TestTerminateWorkflow(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	workflowDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowYamlStr, &workflowDefinition)
-//	if err != nil {
-//		panic(err)
-//	}
-//
-//	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	err = argo.GetInstance().TerminateWorkflow(client.TerminateWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	for {
-//		currentWorkflowDefinitions, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//
-//		if currentWorkflowDefinitions["status"].(map[string]any)["phase"] != "Running" {
-//			break
-//		}
-//
-//		time.Sleep(1 * time.Second)
-//	}
-//}
-//
-//func TestSetWorkflow(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	workflowDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowYamlStr, &workflowDefinition)
-//	if err != nil {
-//		panic(err)
-//	}
-//
-//	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	for {
-//		currentWorkflowDefinitions, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//
-//		nodes, ok := currentWorkflowDefinitions["status"].(map[string]any)["nodes"]
-//		if !ok {
-//			time.Sleep(1 * time.Second)
-//			continue
-//		}
-//
-//		findA := false
-//		nodesMap := nodes.(map[string]any)
-//		for _, node := range nodesMap {
-//			nodeMap := node.(map[string]any)
-//			if nodeMap["displayName"].(string) == "A" {
-//				findA = true
-//			}
-//		}
-//
-//		if findA {
-//			break
-//		}
-//
-//		time.Sleep(1 * time.Second)
-//	}
-//
-//	err = argo.GetInstance().SetWorkflow(client.SetWorkflowParams{
-//		Namespace:         namespace,
-//		Name:              workflowName,
-//		NodeFieldSelector: "displayName=A",
-//		OutputParameters:  `{"approve": "pass"}`,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	currentWorkflowDefinitions, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	nodesMap := currentWorkflowDefinitions["status"].(map[string]any)["nodes"].(map[string]any)
-//	for _, node := range nodesMap {
-//		nodeMap := node.(map[string]any)
-//		if nodeMap["displayName"].(string) == "A" {
-//			outputParams := nodeMap["outputs"].(map[string]any)["parameters"].([]any)
-//			approveParamsMap := outputParams[0].(map[string]any)
-//			if approveParamsMap["name"] == "approve" && approveParamsMap["value"] == "pass" {
-//				return
-//			}
-//
-//			t.Fatalf("%+v\n", errors.Errorf("输出参数不正确: %v", approveParamsMap["value"]))
-//		}
-//	}
-//
-//	t.Fatalf("%+v\n", errors.New("找不到对应的节点"))
-//}
-//
-//func TestSuspendAndResumeWorkflow(t *testing.T) {
-//	err := argo.Init(kubeConfig)
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer argo.Destroy()
-//
-//	workflowDefinition := make(map[string]any)
-//	err := yaml.Unmarshal(workflowWithParamsYamlStr, &workflowDefinition)
-//	if err != nil {
-//		panic(err)
-//	}
-//
-//	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
-//		Namespace:          namespace,
-//		WorkflowDefinition: workflowDefinition,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	defer func() {
-//		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//	}()
-//
-//	err = argo.GetInstance().SuspendWorkflow(client.SuspendWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	for {
-//		currentWorkflowDefinitions, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//
-//		if currentWorkflowDefinitions["spec"].(map[string]any)["suspend"] == true {
-//			break
-//		}
-//
-//		time.Sleep(1 * time.Second)
-//	}
-//
-//	err = argo.GetInstance().ResumeWorkflow(client.ResumeWorkflowParams{
-//		Namespace: namespace,
-//		Name:      workflowName,
-//	})
-//	if err != nil {
-//		t.Fatalf("%+v\n", err)
-//	}
-//
-//	for {
-//		currentWorkflowDefinitions, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
-//			Namespace: namespace,
-//			Name:      workflowName,
-//		})
-//		if err != nil {
-//			t.Fatalf("%+v\n", err)
-//		}
-//
-//		_, ok := currentWorkflowDefinitions["spec"].(map[string]any)["suspend"]
-//		if !ok {
-//			break
-//		}
-//
-//		time.Sleep(1 * time.Second)
-//	}
-//}
+import (
+	"git.sxidc.com/go-tools/argo-api"
+	"git.sxidc.com/go-tools/argo-api/client"
+	"github.com/pkg/errors"
+	"testing"
+	"time"
+)
+
+func TestWorkflowBase(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	err = argo.GetInstance().LintWorkflow(client.LintWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	wfs, err := argo.GetInstance().GetWorkflowsInNamespace(client.GetWorkflowsInNamespaceParams{
+		Namespace: namespace,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(wfs) != 1 {
+		t.Fatalf("%+v\n", errors.Errorf("数量不一致: %v", len(wfs)))
+	}
+
+	wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if wf.Namespace != wfs[0].Namespace {
+		t.Fatalf("%+v\n", errors.Errorf("命名空间不一致: one: %s other: %s", wf.Namespace, wfs[0].Namespace))
+	}
+
+	if wf.Name != wfs[0].Name {
+		t.Fatalf("%+v\n", errors.Errorf("名称不一致: one: %s other: %s", wf.Name, wfs[0].Name))
+	}
+}
+
+func TestSubmitWorkflow(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	err = argo.GetInstance().CreateWorkflowTemplate(client.CreateWorkflowTemplateParams{
+		Namespace:          namespace,
+		TemplateDefinition: workflowTemplateWithParamsYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflowTemplate(client.DeleteWorkflowTemplateParams{
+			Namespace: namespace,
+			Name:      workflowTemplateWithParamsName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	submitWorkflowName, err := argo.GetInstance().SubmitWorkflowFromWorkflowTemplate(client.SubmitWorkflowFromWorkflowTemplateParams{
+		Namespace:    namespace,
+		TemplateName: workflowTemplateWithParamsName,
+		Parameters:   []string{"message=Hello Submit"},
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      submitWorkflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+		Namespace: namespace,
+		Name:      submitWorkflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if wf.Spec.Arguments.Parameters[0].Name != "message" {
+		t.Fatalf("%+v\n", errors.Errorf("参数名称错误: %v", wf.Spec.Arguments.Parameters[0].Name))
+	}
+
+	if wf.Spec.Arguments.Parameters[0].Value.String() != "Hello Submit" {
+		t.Fatalf("%+v\n", errors.Errorf("参数值错误: %v", wf.Spec.Arguments.Parameters[0].Value.String()))
+	}
+}
+
+func TestResubmitWorkflow(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	resubmittedWorkflowName, err := argo.GetInstance().ResubmitWorkflow(client.ResubmitWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      resubmittedWorkflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+}
+
+func TestRetryWorkflow(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	err = argo.GetInstance().TerminateWorkflow(client.TerminateWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	for {
+		wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+
+		if wf.Status.Phase != "Running" {
+			break
+		}
+
+		time.Sleep(1 * time.Second)
+	}
+
+	err = argo.GetInstance().RetryWorkflow(client.RetryWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+}
+
+func TestStopWorkflow(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	err = argo.GetInstance().StopWorkflow(client.StopWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	for {
+		wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+
+		if wf.Status.Phase != "Running" {
+			break
+		}
+
+		time.Sleep(1 * time.Second)
+	}
+}
+
+func TestTerminateWorkflow(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	err = argo.GetInstance().TerminateWorkflow(client.TerminateWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	for {
+		wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+
+		if wf.Status.Phase != "Running" {
+			break
+		}
+
+		time.Sleep(1 * time.Second)
+	}
+}
+
+func TestSetWorkflow(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	for {
+		wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+
+		findA := false
+		for _, node := range wf.Status.Nodes {
+			if node.DisplayName == "A" {
+				findA = true
+			}
+		}
+
+		if findA {
+			break
+		}
+
+		time.Sleep(1 * time.Second)
+	}
+
+	err = argo.GetInstance().SetWorkflow(client.SetWorkflowParams{
+		Namespace:         namespace,
+		Name:              workflowName,
+		NodeFieldSelector: "displayName=A",
+		OutputParameters:  `{"approve": "pass"}`,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	for _, node := range wf.Status.Nodes {
+		if node.DisplayName == "A" {
+			if node.Outputs.Parameters[0].Name == "approve" && node.Outputs.Parameters[0].Value.String() == "pass" {
+				return
+			}
+
+			t.Fatalf("%+v\n", errors.Errorf("输出参数不正确: %v", node.Outputs.Parameters[0].Value.String()))
+		}
+	}
+
+	t.Fatalf("%+v\n", errors.New("找不到对应的节点"))
+}
+
+func TestSuspendAndResumeWorkflow(t *testing.T) {
+	err := argo.Init(kubeConfig)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer argo.Destroy()
+
+	workflowName, err := argo.GetInstance().CreateWorkflow(client.CreateWorkflowParams{
+		Namespace:          namespace,
+		WorkflowDefinition: workflowWithParamsYamlStr,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	defer func() {
+		err := argo.GetInstance().DeleteWorkflow(client.DeleteWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+	}()
+
+	err = argo.GetInstance().SuspendWorkflow(client.SuspendWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	for {
+		wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+
+		if wf.Spec.Suspend != nil && *wf.Spec.Suspend == true {
+			break
+		}
+
+		time.Sleep(1 * time.Second)
+	}
+
+	err = argo.GetInstance().ResumeWorkflow(client.ResumeWorkflowParams{
+		Namespace: namespace,
+		Name:      workflowName,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	for {
+		wf, err := argo.GetInstance().GetWorkflow(client.GetWorkflowParams{
+			Namespace: namespace,
+			Name:      workflowName,
+		})
+		if err != nil {
+			t.Fatalf("%+v\n", err)
+		}
+
+		if wf.Spec.Suspend == nil || *wf.Spec.Suspend == false {
+			break
+		}
+
+		time.Sleep(1 * time.Second)
+	}
+}