github.com/oam-dev/kubevela@v1.9.11/pkg/workflow/step/generator_test.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package step
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/stretchr/testify/require"
    25  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    28  
    29  	workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
    30  
    31  	"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    32  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
    33  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    34  	common2 "github.com/oam-dev/kubevela/pkg/utils/common"
    35  )
    36  
    37  func TestWorkflowStepGenerator(t *testing.T) {
    38  	r := require.New(t)
    39  	cli := fake.NewClientBuilder().WithScheme(common2.Scheme).WithObjects(&workflowv1alpha1.Workflow{
    40  		ObjectMeta: v1.ObjectMeta{
    41  			Name:      "ref-wf",
    42  			Namespace: "test",
    43  		},
    44  		WorkflowSpec: workflowv1alpha1.WorkflowSpec{
    45  			Steps: []workflowv1alpha1.WorkflowStep{{
    46  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
    47  					Name: "manual-approve",
    48  					Type: "suspend",
    49  				},
    50  			}, {
    51  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
    52  					Name: "deploy",
    53  					Type: "deploy",
    54  				},
    55  			}},
    56  		},
    57  	}).Build()
    58  	testCases := map[string]struct {
    59  		input    []workflowv1alpha1.WorkflowStep
    60  		app      *v1beta1.Application
    61  		output   []workflowv1alpha1.WorkflowStep
    62  		hasError bool
    63  	}{
    64  		"apply-component-with-existing-steps": {
    65  			input: []workflowv1alpha1.WorkflowStep{{
    66  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
    67  					Name:       "example-comp-1",
    68  					Type:       "apply-component",
    69  					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"example-comp-1"}`)},
    70  				},
    71  			}},
    72  			app: &v1beta1.Application{
    73  				Spec: v1beta1.ApplicationSpec{
    74  					Components: []common.ApplicationComponent{{
    75  						Name: "example-comp-1",
    76  					}, {
    77  						Name: "example-comp-2",
    78  					}},
    79  				},
    80  			},
    81  			output: []workflowv1alpha1.WorkflowStep{{
    82  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
    83  					Name:       "example-comp-1",
    84  					Type:       "apply-component",
    85  					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"example-comp-1"}`)},
    86  				},
    87  			}},
    88  		},
    89  		"apply-component-with-no-steps": {
    90  			input: []workflowv1alpha1.WorkflowStep{},
    91  			app: &v1beta1.Application{
    92  				Spec: v1beta1.ApplicationSpec{
    93  					Components: []common.ApplicationComponent{{
    94  						Name: "example-comp-1",
    95  					}, {
    96  						Name: "example-comp-2",
    97  					}},
    98  				},
    99  			},
   100  			output: []workflowv1alpha1.WorkflowStep{{
   101  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   102  					Name:       "example-comp-1",
   103  					Type:       "apply-component",
   104  					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"example-comp-1"}`)},
   105  				},
   106  			}, {
   107  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   108  					Name:       "example-comp-2",
   109  					Type:       "apply-component",
   110  					Properties: &runtime.RawExtension{Raw: []byte(`{"component":"example-comp-2"}`)},
   111  				},
   112  			}},
   113  		},
   114  		"env-binding-bad": {
   115  			input: []workflowv1alpha1.WorkflowStep{},
   116  			app: &v1beta1.Application{
   117  				Spec: v1beta1.ApplicationSpec{
   118  					Components: []common.ApplicationComponent{{
   119  						Name: "example-comp-1",
   120  					}},
   121  					Policies: []v1beta1.AppPolicy{{
   122  						Name:       "example-policy",
   123  						Type:       v1alpha1.EnvBindingPolicyType,
   124  						Properties: &runtime.RawExtension{Raw: []byte(`bad value`)},
   125  					}},
   126  				},
   127  			},
   128  			hasError: true,
   129  		},
   130  		"env-binding-correct": {
   131  			input: []workflowv1alpha1.WorkflowStep{},
   132  			app: &v1beta1.Application{
   133  				Spec: v1beta1.ApplicationSpec{
   134  					Components: []common.ApplicationComponent{{
   135  						Name: "example-comp-1",
   136  					}},
   137  					Policies: []v1beta1.AppPolicy{{
   138  						Name:       "example-policy",
   139  						Type:       v1alpha1.EnvBindingPolicyType,
   140  						Properties: &runtime.RawExtension{Raw: []byte(`{"envs":[{"name":"env-1"},{"name":"env-2"}]}`)},
   141  					}},
   142  				},
   143  			},
   144  			output: []workflowv1alpha1.WorkflowStep{{
   145  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   146  					Name:       "deploy-example-policy-env-1",
   147  					Type:       "deploy2env",
   148  					Properties: &runtime.RawExtension{Raw: []byte(`{"env":"env-1","policy":"example-policy"}`)},
   149  				},
   150  			}, {
   151  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   152  					Name:       "deploy-example-policy-env-2",
   153  					Type:       "deploy2env",
   154  					Properties: &runtime.RawExtension{Raw: []byte(`{"env":"env-2","policy":"example-policy"}`)},
   155  				},
   156  			}},
   157  		},
   158  		"deploy-workflow": {
   159  			input: []workflowv1alpha1.WorkflowStep{},
   160  			app: &v1beta1.Application{
   161  				Spec: v1beta1.ApplicationSpec{
   162  					Components: []common.ApplicationComponent{{
   163  						Name: "example-comp-1",
   164  					}},
   165  					Policies: []v1beta1.AppPolicy{{
   166  						Name: "example-topology-policy-1",
   167  						Type: v1alpha1.TopologyPolicyType,
   168  					}, {
   169  						Name: "example-topology-policy-2",
   170  						Type: v1alpha1.TopologyPolicyType,
   171  					}, {
   172  						Name: "example-override-policy-1",
   173  						Type: v1alpha1.OverridePolicyType,
   174  					}, {
   175  						Name: "example-override-policy-2",
   176  						Type: v1alpha1.OverridePolicyType,
   177  					}},
   178  				},
   179  			},
   180  			output: []workflowv1alpha1.WorkflowStep{{
   181  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   182  					Name:       "deploy-example-topology-policy-1",
   183  					Type:       "deploy",
   184  					Properties: &runtime.RawExtension{Raw: []byte(`{"policies":["example-override-policy-1","example-override-policy-2","example-topology-policy-1"]}`)},
   185  				},
   186  			}, {
   187  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   188  					Name:       "deploy-example-topology-policy-2",
   189  					Type:       "deploy",
   190  					Properties: &runtime.RawExtension{Raw: []byte(`{"policies":["example-override-policy-1","example-override-policy-2","example-topology-policy-2"]}`)},
   191  				},
   192  			}},
   193  		},
   194  		"deploy-with-ref-without-po-workflow": {
   195  			input: []workflowv1alpha1.WorkflowStep{},
   196  			app: &v1beta1.Application{
   197  				Spec: v1beta1.ApplicationSpec{
   198  					Components: []common.ApplicationComponent{{
   199  						Name: "example-comp",
   200  						Type: "ref-objects",
   201  					}},
   202  				},
   203  			},
   204  			output: []workflowv1alpha1.WorkflowStep{{
   205  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   206  					Name:       "deploy",
   207  					Type:       "deploy",
   208  					Properties: &runtime.RawExtension{Raw: []byte(`{"policies":[]}`)},
   209  				},
   210  			}},
   211  		},
   212  		"ref-workflow": {
   213  			input: nil,
   214  			app: &v1beta1.Application{
   215  				ObjectMeta: v1.ObjectMeta{
   216  					Namespace: "test",
   217  				},
   218  				Spec: v1beta1.ApplicationSpec{
   219  					Workflow: &v1beta1.Workflow{
   220  						Ref: "ref-wf",
   221  					},
   222  				},
   223  			},
   224  			output: []workflowv1alpha1.WorkflowStep{{
   225  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   226  					Name: "manual-approve",
   227  					Type: "suspend",
   228  				},
   229  			}, {
   230  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   231  					Name: "deploy",
   232  					Type: "deploy",
   233  				},
   234  			}},
   235  		},
   236  		"ref-workflow-conflict": {
   237  			input: []workflowv1alpha1.WorkflowStep{{
   238  				WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   239  					Name: "deploy",
   240  					Type: "deploy",
   241  				},
   242  			}},
   243  			app: &v1beta1.Application{
   244  				ObjectMeta: v1.ObjectMeta{
   245  					Namespace: "test",
   246  				},
   247  				Spec: v1beta1.ApplicationSpec{
   248  					Workflow: &v1beta1.Workflow{
   249  						Ref: "ref-wf",
   250  						Steps: []workflowv1alpha1.WorkflowStep{{
   251  							WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
   252  								Name: "deploy",
   253  								Type: "deploy",
   254  							},
   255  						}},
   256  					},
   257  				},
   258  			},
   259  			hasError: true,
   260  		},
   261  		"ref-workflow-not-found": {
   262  			input: nil,
   263  			app: &v1beta1.Application{
   264  				ObjectMeta: v1.ObjectMeta{
   265  					Namespace: "test",
   266  				},
   267  				Spec: v1beta1.ApplicationSpec{
   268  					Workflow: &v1beta1.Workflow{
   269  						Ref: "ref-wf-404",
   270  					},
   271  				},
   272  			},
   273  			hasError: true,
   274  		},
   275  	}
   276  	generator := NewChainWorkflowStepGenerator(
   277  		&RefWorkflowStepGenerator{Context: context.Background(), Client: cli},
   278  		&DeployWorkflowStepGenerator{},
   279  		&Deploy2EnvWorkflowStepGenerator{},
   280  		&ApplyComponentWorkflowStepGenerator{},
   281  	)
   282  	for name, testCase := range testCases {
   283  		t.Run(name, func(t *testing.T) {
   284  			output, err := generator.Generate(testCase.app, testCase.input)
   285  			if testCase.hasError {
   286  				r.Error(err)
   287  			} else {
   288  				r.NoError(err)
   289  				r.Equal(testCase.output, output)
   290  			}
   291  		})
   292  	}
   293  }
   294  
   295  func TestIsBuiltinWorkflowStepType(t *testing.T) {
   296  	assert.True(t, IsBuiltinWorkflowStepType("suspend"))
   297  	assert.True(t, IsBuiltinWorkflowStepType("apply-component"))
   298  	assert.True(t, IsBuiltinWorkflowStepType("step-group"))
   299  	assert.True(t, IsBuiltinWorkflowStepType("builtin-apply-component"))
   300  }