github.com/kubevela/workflow@v0.6.0/pkg/providers/util/util_test.go (about)

     1  /*
     2   Copyright 2022. 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 util
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"errors"
    23  	"fmt"
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/require"
    27  	corev1 "k8s.io/api/core/v1"
    28  	"sigs.k8s.io/yaml"
    29  
    30  	monitorContext "github.com/kubevela/pkg/monitor/context"
    31  
    32  	wfContext "github.com/kubevela/workflow/pkg/context"
    33  	"github.com/kubevela/workflow/pkg/cue/model"
    34  	"github.com/kubevela/workflow/pkg/cue/model/value"
    35  	"github.com/kubevela/workflow/pkg/cue/process"
    36  	"github.com/kubevela/workflow/pkg/providers"
    37  )
    38  
    39  func TestPatchK8sObject(t *testing.T) {
    40  	testcases := map[string]struct {
    41  		value       string
    42  		expectedErr error
    43  		patchResult string
    44  	}{
    45  		"test patch k8s object": {
    46  			value: `
    47  value: {
    48  	apiVersion: "apps/v1"
    49  	kind:       "Deployment"
    50  	spec: template: metadata: {
    51  		labels: {
    52  			"oam.dev/name": "test"
    53  		}
    54  	}
    55  }
    56  patch: {
    57  	spec: template: metadata: {
    58  		labels: {
    59  			"test-label": "true"
    60  		}
    61  	}
    62  }
    63  `,
    64  			expectedErr: nil,
    65  			patchResult: `
    66  apiVersion: "apps/v1"
    67  kind:       "Deployment"
    68  spec: template: metadata: {
    69  	labels: {
    70  		"oam.dev/name": "test"
    71  		"test-label":   "true"
    72  	}
    73  }
    74  `,
    75  		},
    76  		"test patch k8s object with patchKey": {
    77  			value: `
    78  value: {
    79  	apiVersion: "apps/v1"
    80  	kind:       "Deployment"
    81  	spec: template: spec: {
    82  		containers: [{
    83  			name: "test"
    84  		}]
    85  	}
    86  }
    87  patch: {
    88  	spec: template: spec: {
    89  		// +patchKey=name
    90  		containers: [{
    91  			name: "test"
    92  			env: [{
    93  				name:  "test-env"
    94  				value: "test-value"
    95  			}]
    96  		}]
    97  	}
    98  }
    99  `,
   100  			expectedErr: nil,
   101  			patchResult: `
   102  apiVersion: "apps/v1"
   103  kind:       "Deployment"
   104  spec: template: spec: {
   105  	containers: [{
   106  		name: "test"
   107  		env: [{
   108  			name:  "test-env"
   109  			value: "test-value"
   110  		}]
   111  	}]
   112  }
   113  `,
   114  		},
   115  		"test patch k8s object with patchStrategy": {
   116  			value: `
   117  value: {
   118  	apiVersion: "apps/v1"
   119  	kind:       "Deployment"
   120  	spec: template: metadata: {
   121  		name: "test-name"
   122  	}
   123  }
   124  patch: {
   125  	// +patchStrategy=retainKeys
   126  	spec: template: metadata: {
   127  		name: "test-patchStrategy"
   128  	}
   129  }
   130  `,
   131  			expectedErr: nil,
   132  			patchResult: `
   133  apiVersion: "apps/v1"
   134  kind:       "Deployment"
   135  spec: template: metadata: {
   136  	name: "test-patchStrategy"
   137  }
   138  `,
   139  		},
   140  	}
   141  
   142  	for name, tc := range testcases {
   143  		t.Run(name, func(t *testing.T) {
   144  			r := require.New(t)
   145  			v, err := value.NewValue(tc.value, nil, "")
   146  			r.NoError(err)
   147  			prd := &provider{}
   148  			err = prd.PatchK8sObject(nil, nil, v, nil)
   149  			if tc.expectedErr != nil {
   150  				r.Equal(tc.expectedErr.Error(), err.Error())
   151  				return
   152  			}
   153  			r.NoError(err)
   154  			result, err := v.LookupValue("result")
   155  			r.NoError(err)
   156  			var patchResult map[string]interface{}
   157  			r.NoError(result.UnmarshalTo(&patchResult))
   158  			var expectResult map[string]interface{}
   159  			resultValue, err := value.NewValue(tc.patchResult, nil, "")
   160  			r.NoError(err)
   161  			r.NoError(resultValue.UnmarshalTo(&expectResult))
   162  			r.Equal(expectResult, patchResult)
   163  		})
   164  	}
   165  }
   166  
   167  func TestConvertString(t *testing.T) {
   168  	testCases := map[string]struct {
   169  		from        string
   170  		expected    string
   171  		expectedErr error
   172  	}{
   173  		"success": {
   174  			from:     `bt: 'test'`,
   175  			expected: "test",
   176  		},
   177  		"fail": {
   178  			from:        `bt: 123`,
   179  			expectedErr: errors.New("bt: cannot use value 123 (type int) as (string|bytes)"),
   180  		},
   181  	}
   182  
   183  	for name, tc := range testCases {
   184  		t.Run(name, func(t *testing.T) {
   185  			r := require.New(t)
   186  			v, err := value.NewValue(tc.from, nil, "")
   187  			r.NoError(err)
   188  			prd := &provider{}
   189  			err = prd.String(nil, nil, v, nil)
   190  			if tc.expectedErr != nil {
   191  				r.Equal(tc.expectedErr.Error(), err.Error())
   192  				return
   193  			}
   194  			r.NoError(err)
   195  			expected, err := v.LookupValue("str")
   196  			r.NoError(err)
   197  			ret, err := expected.CueValue().String()
   198  			r.NoError(err)
   199  			r.Equal(ret, tc.expected)
   200  		})
   201  	}
   202  }
   203  
   204  func TestLog(t *testing.T) {
   205  	wfCtx := newWorkflowContextForTest(t)
   206  	pCtx := process.NewContext(process.ContextData{})
   207  	pCtx.PushData(model.ContextStepName, "test-step")
   208  	prd := &provider{pCtx: pCtx}
   209  	logCtx := monitorContext.NewTraceContext(context.Background(), "")
   210  
   211  	testCases := []struct {
   212  		value       string
   213  		expected    string
   214  		expectedErr string
   215  	}{
   216  		{
   217  			value:    `data: "test"`,
   218  			expected: `{"test-step":{"data":true}}`,
   219  		},
   220  		{
   221  			value: `
   222  data: {
   223  	message: "test"
   224  }
   225  level: 3`,
   226  			expected: `{"test-step":{"data":true}}`,
   227  		},
   228  		{
   229  			value:    `test: ""`,
   230  			expected: `{"test-step":{"data":true}}`,
   231  		},
   232  		{
   233  			value: `
   234  source: {
   235  	url: "https://kubevela.io"
   236  }
   237  `,
   238  			expected: `{"test-step":{"data":true,"source":{"url":"https://kubevela.io"}}}`,
   239  		},
   240  		{
   241  			value: `
   242  source: {
   243  	resources: [{
   244  		labelSelector: {"test": "test"}
   245  	}]
   246  }
   247  `,
   248  			expected: `{"test-step":{"data":true,"source":{"url":"https://kubevela.io","resources":[{"labelSelector":{"test":"test"}}]}}}`,
   249  		},
   250  		{
   251  			value: `
   252  source: {
   253  	resources: [{
   254  		name: "test"
   255  		namespace: "test"
   256  		cluster: "test"
   257  	}]
   258  }
   259  `,
   260  			expected: `{"test-step":{"data":true,"source":{"url":"https://kubevela.io","resources":[{"name":"test","namespace":"test","cluster":"test"}]}}}`,
   261  		},
   262  		{
   263  			value: `
   264  source: {
   265  	url: "https://kubevela.com"
   266  }
   267  `,
   268  			expected: `{"test-step":{"data":true,"source":{"url":"https://kubevela.com","resources":[{"name":"test","namespace":"test","cluster":"test"}]}}}`,
   269  		},
   270  	}
   271  	for i, tc := range testCases {
   272  		t.Run(fmt.Sprint(i), func(t *testing.T) {
   273  			r := require.New(t)
   274  			v, err := value.NewValue(tc.value, nil, "")
   275  			r.NoError(err)
   276  			err = prd.Log(logCtx, wfCtx, v, nil)
   277  			if tc.expectedErr != "" {
   278  				r.Contains(err.Error(), tc.expectedErr)
   279  				return
   280  			}
   281  			r.NoError(err)
   282  			if tc.expected != "" {
   283  				config := wfCtx.GetMutableValue("logConfig")
   284  				r.Equal(tc.expected, config)
   285  			}
   286  		})
   287  	}
   288  }
   289  
   290  func TestInstall(t *testing.T) {
   291  	p := providers.NewProviders()
   292  	pCtx := process.NewContext(process.ContextData{})
   293  	pCtx.PushData(model.ContextStepName, "test-step")
   294  	Install(p, pCtx)
   295  	h, ok := p.GetHandler("util", "string")
   296  	r := require.New(t)
   297  	r.Equal(ok, true)
   298  	r.Equal(h != nil, true)
   299  }
   300  
   301  func newWorkflowContextForTest(t *testing.T) wfContext.Context {
   302  	cm := corev1.ConfigMap{}
   303  	r := require.New(t)
   304  	testCaseJson, err := yaml.YAMLToJSON([]byte(testCaseYaml))
   305  	r.NoError(err)
   306  	err = json.Unmarshal(testCaseJson, &cm)
   307  	r.NoError(err)
   308  
   309  	wfCtx := new(wfContext.WorkflowContext)
   310  	err = wfCtx.LoadFromConfigMap(cm)
   311  	r.NoError(err)
   312  	return wfCtx
   313  }
   314  
   315  var (
   316  	testCaseYaml = `apiVersion: v1
   317  data:
   318    logConfig: ""
   319  kind: ConfigMap
   320  metadata:
   321    name: app-v1
   322  `
   323  )