github.com/argoproj/argo-cd/v2@v2.10.9/applicationset/generators/generator_spec_processor_test.go (about)

     1  package generators
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	log "github.com/sirupsen/logrus"
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  
    13  	"github.com/argoproj/argo-cd/v2/applicationset/services/mocks"
    14  
    15  	argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    16  
    17  	"github.com/stretchr/testify/mock"
    18  	corev1 "k8s.io/api/core/v1"
    19  	"k8s.io/apimachinery/pkg/runtime"
    20  	kubefake "k8s.io/client-go/kubernetes/fake"
    21  	crtclient "sigs.k8s.io/controller-runtime/pkg/client"
    22  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    23  )
    24  
    25  func TestMatchValues(t *testing.T) {
    26  	testCases := []struct {
    27  		name     string
    28  		elements []apiextensionsv1.JSON
    29  		selector *metav1.LabelSelector
    30  		expected []map[string]interface{}
    31  	}{
    32  		{
    33  			name:     "no filter",
    34  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
    35  			selector: &metav1.LabelSelector{},
    36  			expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
    37  		},
    38  		{
    39  			name:     "nil",
    40  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
    41  			selector: nil,
    42  			expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
    43  		},
    44  		{
    45  			name:     "values.foo should be foo but is ignore element",
    46  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
    47  			selector: &metav1.LabelSelector{
    48  				MatchLabels: map[string]string{
    49  					"values.foo": "foo",
    50  				},
    51  			},
    52  			expected: []map[string]interface{}{},
    53  		},
    54  		{
    55  			name:     "values.foo should be bar",
    56  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
    57  			selector: &metav1.LabelSelector{
    58  				MatchLabels: map[string]string{
    59  					"values.foo": "bar",
    60  				},
    61  			},
    62  			expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values.foo": "bar"}},
    63  		},
    64  	}
    65  
    66  	for _, testCase := range testCases {
    67  		t.Run(testCase.name, func(t *testing.T) {
    68  			var listGenerator = NewListGenerator()
    69  			var data = map[string]Generator{
    70  				"List": listGenerator,
    71  			}
    72  
    73  			applicationSetInfo := argov1alpha1.ApplicationSet{
    74  				ObjectMeta: metav1.ObjectMeta{
    75  					Name: "set",
    76  				},
    77  				Spec: argov1alpha1.ApplicationSetSpec{
    78  					GoTemplate: false,
    79  				},
    80  			}
    81  
    82  			results, err := Transform(argov1alpha1.ApplicationSetGenerator{
    83  				Selector: testCase.selector,
    84  				List: &argov1alpha1.ListGenerator{
    85  					Elements: testCase.elements,
    86  					Template: emptyTemplate(),
    87  				}},
    88  				data,
    89  				emptyTemplate(),
    90  				&applicationSetInfo, nil)
    91  
    92  			assert.NoError(t, err)
    93  			assert.ElementsMatch(t, testCase.expected, results[0].Params)
    94  		})
    95  	}
    96  }
    97  
    98  func TestMatchValuesGoTemplate(t *testing.T) {
    99  	testCases := []struct {
   100  		name     string
   101  		elements []apiextensionsv1.JSON
   102  		selector *metav1.LabelSelector
   103  		expected []map[string]interface{}
   104  	}{
   105  		{
   106  			name:     "no filter",
   107  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
   108  			selector: &metav1.LabelSelector{},
   109  			expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
   110  		},
   111  		{
   112  			name:     "nil",
   113  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url"}`)}},
   114  			selector: nil,
   115  			expected: []map[string]interface{}{{"cluster": "cluster", "url": "url"}},
   116  		},
   117  		{
   118  			name:     "values.foo should be foo but is ignore element",
   119  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
   120  			selector: &metav1.LabelSelector{
   121  				MatchLabels: map[string]string{
   122  					"values.foo": "foo",
   123  				},
   124  			},
   125  			expected: []map[string]interface{}{},
   126  		},
   127  		{
   128  			name:     "values.foo should be bar",
   129  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
   130  			selector: &metav1.LabelSelector{
   131  				MatchLabels: map[string]string{
   132  					"values.foo": "bar",
   133  				},
   134  			},
   135  			expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values": map[string]interface{}{"foo": "bar"}}},
   136  		},
   137  		{
   138  			name:     "values.0 should be bar",
   139  			elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":["bar"]}`)}},
   140  			selector: &metav1.LabelSelector{
   141  				MatchLabels: map[string]string{
   142  					"values.0": "bar",
   143  				},
   144  			},
   145  			expected: []map[string]interface{}{{"cluster": "cluster", "url": "url", "values": []interface{}{"bar"}}},
   146  		},
   147  	}
   148  
   149  	for _, testCase := range testCases {
   150  		t.Run(testCase.name, func(t *testing.T) {
   151  			var listGenerator = NewListGenerator()
   152  			var data = map[string]Generator{
   153  				"List": listGenerator,
   154  			}
   155  
   156  			applicationSetInfo := argov1alpha1.ApplicationSet{
   157  				ObjectMeta: metav1.ObjectMeta{
   158  					Name: "set",
   159  				},
   160  				Spec: argov1alpha1.ApplicationSetSpec{
   161  					GoTemplate: true,
   162  				},
   163  			}
   164  
   165  			results, err := Transform(argov1alpha1.ApplicationSetGenerator{
   166  				Selector: testCase.selector,
   167  				List: &argov1alpha1.ListGenerator{
   168  					Elements: testCase.elements,
   169  					Template: emptyTemplate(),
   170  				}},
   171  				data,
   172  				emptyTemplate(),
   173  				&applicationSetInfo, nil)
   174  
   175  			assert.NoError(t, err)
   176  			assert.ElementsMatch(t, testCase.expected, results[0].Params)
   177  		})
   178  	}
   179  }
   180  
   181  func TestTransForm(t *testing.T) {
   182  	testCases := []struct {
   183  		name     string
   184  		selector *metav1.LabelSelector
   185  		expected []map[string]interface{}
   186  	}{
   187  		{
   188  			name: "server filter",
   189  			selector: &metav1.LabelSelector{
   190  				MatchLabels: map[string]string{"server": "https://production-01.example.com"},
   191  			},
   192  			expected: []map[string]interface{}{{
   193  				"metadata.annotations.foo.argoproj.io":           "production",
   194  				"metadata.labels.argocd.argoproj.io/secret-type": "cluster",
   195  				"metadata.labels.environment":                    "production",
   196  				"metadata.labels.org":                            "bar",
   197  				"name":                                           "production_01/west",
   198  				"nameNormalized":                                 "production-01-west",
   199  				"server":                                         "https://production-01.example.com",
   200  			}},
   201  		},
   202  		{
   203  			name: "server filter with long url",
   204  			selector: &metav1.LabelSelector{
   205  				MatchLabels: map[string]string{"server": "https://some-really-long-url-that-will-exceed-63-characters.com"},
   206  			},
   207  			expected: []map[string]interface{}{{
   208  				"metadata.annotations.foo.argoproj.io":           "production",
   209  				"metadata.labels.argocd.argoproj.io/secret-type": "cluster",
   210  				"metadata.labels.environment":                    "production",
   211  				"metadata.labels.org":                            "bar",
   212  				"name":                                           "some-really-long-server-url",
   213  				"nameNormalized":                                 "some-really-long-server-url",
   214  				"server":                                         "https://some-really-long-url-that-will-exceed-63-characters.com",
   215  			}},
   216  		},
   217  	}
   218  
   219  	for _, testCase := range testCases {
   220  		t.Run(testCase.name, func(t *testing.T) {
   221  			testGenerators := map[string]Generator{
   222  				"Clusters": getMockClusterGenerator(),
   223  			}
   224  
   225  			applicationSetInfo := argov1alpha1.ApplicationSet{
   226  				ObjectMeta: metav1.ObjectMeta{
   227  					Name: "set",
   228  				},
   229  				Spec: argov1alpha1.ApplicationSetSpec{},
   230  			}
   231  
   232  			results, err := Transform(
   233  				argov1alpha1.ApplicationSetGenerator{
   234  					Selector: testCase.selector,
   235  					Clusters: &argov1alpha1.ClusterGenerator{
   236  						Selector: metav1.LabelSelector{},
   237  						Template: argov1alpha1.ApplicationSetTemplate{},
   238  						Values:   nil,
   239  					}},
   240  				testGenerators,
   241  				emptyTemplate(),
   242  				&applicationSetInfo, nil)
   243  
   244  			assert.NoError(t, err)
   245  			assert.ElementsMatch(t, testCase.expected, results[0].Params)
   246  		})
   247  	}
   248  }
   249  
   250  func emptyTemplate() argov1alpha1.ApplicationSetTemplate {
   251  	return argov1alpha1.ApplicationSetTemplate{
   252  		Spec: argov1alpha1.ApplicationSpec{
   253  			Project: "project",
   254  		},
   255  	}
   256  }
   257  
   258  func getMockClusterGenerator() Generator {
   259  	clusters := []crtclient.Object{
   260  		&corev1.Secret{
   261  			TypeMeta: metav1.TypeMeta{
   262  				Kind:       "Secret",
   263  				APIVersion: "v1",
   264  			},
   265  			ObjectMeta: metav1.ObjectMeta{
   266  				Name:      "staging-01",
   267  				Namespace: "namespace",
   268  				Labels: map[string]string{
   269  					"argocd.argoproj.io/secret-type": "cluster",
   270  					"environment":                    "staging",
   271  					"org":                            "foo",
   272  				},
   273  				Annotations: map[string]string{
   274  					"foo.argoproj.io": "staging",
   275  				},
   276  			},
   277  			Data: map[string][]byte{
   278  				"config": []byte("{}"),
   279  				"name":   []byte("staging-01"),
   280  				"server": []byte("https://staging-01.example.com"),
   281  			},
   282  			Type: corev1.SecretType("Opaque"),
   283  		},
   284  		&corev1.Secret{
   285  			TypeMeta: metav1.TypeMeta{
   286  				Kind:       "Secret",
   287  				APIVersion: "v1",
   288  			},
   289  			ObjectMeta: metav1.ObjectMeta{
   290  				Name:      "production-01",
   291  				Namespace: "namespace",
   292  				Labels: map[string]string{
   293  					"argocd.argoproj.io/secret-type": "cluster",
   294  					"environment":                    "production",
   295  					"org":                            "bar",
   296  				},
   297  				Annotations: map[string]string{
   298  					"foo.argoproj.io": "production",
   299  				},
   300  			},
   301  			Data: map[string][]byte{
   302  				"config": []byte("{}"),
   303  				"name":   []byte("production_01/west"),
   304  				"server": []byte("https://production-01.example.com"),
   305  			},
   306  			Type: corev1.SecretType("Opaque"),
   307  		},
   308  		&corev1.Secret{
   309  			TypeMeta: metav1.TypeMeta{
   310  				Kind:       "Secret",
   311  				APIVersion: "v1",
   312  			},
   313  			ObjectMeta: metav1.ObjectMeta{
   314  				Name:      "some-really-long-server-url",
   315  				Namespace: "namespace",
   316  				Labels: map[string]string{
   317  					"argocd.argoproj.io/secret-type": "cluster",
   318  					"environment":                    "production",
   319  					"org":                            "bar",
   320  				},
   321  				Annotations: map[string]string{
   322  					"foo.argoproj.io": "production",
   323  				},
   324  			},
   325  			Data: map[string][]byte{
   326  				"config": []byte("{}"),
   327  				"name":   []byte("some-really-long-server-url"),
   328  				"server": []byte("https://some-really-long-url-that-will-exceed-63-characters.com"),
   329  			},
   330  			Type: corev1.SecretType("Opaque"),
   331  		},
   332  	}
   333  	runtimeClusters := []runtime.Object{}
   334  	for _, clientCluster := range clusters {
   335  		runtimeClusters = append(runtimeClusters, clientCluster)
   336  	}
   337  	appClientset := kubefake.NewSimpleClientset(runtimeClusters...)
   338  
   339  	fakeClient := fake.NewClientBuilder().WithObjects(clusters...).Build()
   340  	return NewClusterGenerator(fakeClient, context.Background(), appClientset, "namespace")
   341  }
   342  
   343  func getMockGitGenerator() Generator {
   344  	argoCDServiceMock := mocks.Repos{}
   345  	argoCDServiceMock.On("GetDirectories", mock.Anything, mock.Anything, mock.Anything).Return([]string{"app1", "app2", "app_3", "p1/app4"}, nil)
   346  	var gitGenerator = NewGitGenerator(&argoCDServiceMock)
   347  	return gitGenerator
   348  }
   349  
   350  func TestGetRelevantGenerators(t *testing.T) {
   351  
   352  	testGenerators := map[string]Generator{
   353  		"Clusters": getMockClusterGenerator(),
   354  		"Git":      getMockGitGenerator(),
   355  	}
   356  
   357  	testGenerators["Matrix"] = NewMatrixGenerator(testGenerators)
   358  	testGenerators["Merge"] = NewMergeGenerator(testGenerators)
   359  	testGenerators["List"] = NewListGenerator()
   360  
   361  	requestedGenerator := &argov1alpha1.ApplicationSetGenerator{
   362  		List: &argov1alpha1.ListGenerator{
   363  			Elements: []apiextensionsv1.JSON{{Raw: []byte(`{"cluster": "cluster","url": "url","values":{"foo":"bar"}}`)}},
   364  		}}
   365  
   366  	relevantGenerators := GetRelevantGenerators(requestedGenerator, testGenerators)
   367  	assert.Len(t, relevantGenerators, 1)
   368  	assert.IsType(t, &ListGenerator{}, relevantGenerators[0])
   369  
   370  	requestedGenerator = &argov1alpha1.ApplicationSetGenerator{
   371  		Clusters: &argov1alpha1.ClusterGenerator{
   372  			Selector: metav1.LabelSelector{},
   373  			Template: argov1alpha1.ApplicationSetTemplate{},
   374  			Values:   nil,
   375  		},
   376  	}
   377  
   378  	relevantGenerators = GetRelevantGenerators(requestedGenerator, testGenerators)
   379  	assert.Len(t, relevantGenerators, 1)
   380  	assert.IsType(t, &ClusterGenerator{}, relevantGenerators[0])
   381  
   382  	requestedGenerator = &argov1alpha1.ApplicationSetGenerator{
   383  		Git: &argov1alpha1.GitGenerator{
   384  			RepoURL:             "",
   385  			Directories:         nil,
   386  			Files:               nil,
   387  			Revision:            "",
   388  			RequeueAfterSeconds: nil,
   389  			Template:            argov1alpha1.ApplicationSetTemplate{},
   390  		},
   391  	}
   392  
   393  	relevantGenerators = GetRelevantGenerators(requestedGenerator, testGenerators)
   394  	assert.Len(t, relevantGenerators, 1)
   395  	assert.IsType(t, &GitGenerator{}, relevantGenerators[0])
   396  }
   397  
   398  func TestInterpolateGenerator(t *testing.T) {
   399  	requestedGenerator := &argov1alpha1.ApplicationSetGenerator{
   400  		Clusters: &argov1alpha1.ClusterGenerator{
   401  			Selector: metav1.LabelSelector{
   402  				MatchLabels: map[string]string{
   403  					"argocd.argoproj.io/secret-type": "cluster",
   404  					"path-basename":                  "{{path.basename}}",
   405  					"path-zero":                      "{{path[0]}}",
   406  					"path-full":                      "{{path}}",
   407  				}},
   408  		},
   409  	}
   410  	gitGeneratorParams := map[string]interface{}{
   411  		"path":                    "p1/p2/app3",
   412  		"path.basename":           "app3",
   413  		"path[0]":                 "p1",
   414  		"path[1]":                 "p2",
   415  		"path.basenameNormalized": "app3",
   416  	}
   417  	interpolatedGenerator, err := InterpolateGenerator(requestedGenerator, gitGeneratorParams, false, nil)
   418  	if err != nil {
   419  		log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
   420  		return
   421  	}
   422  	assert.Equal(t, "app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-basename"])
   423  	assert.Equal(t, "p1", interpolatedGenerator.Clusters.Selector.MatchLabels["path-zero"])
   424  	assert.Equal(t, "p1/p2/app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-full"])
   425  
   426  	fileNamePath := argov1alpha1.GitFileGeneratorItem{
   427  		Path: "{{name}}",
   428  	}
   429  	fileServerPath := argov1alpha1.GitFileGeneratorItem{
   430  		Path: "{{server}}",
   431  	}
   432  
   433  	requestedGenerator = &argov1alpha1.ApplicationSetGenerator{
   434  		Git: &argov1alpha1.GitGenerator{
   435  			Files:    append([]argov1alpha1.GitFileGeneratorItem{}, fileNamePath, fileServerPath),
   436  			Template: argov1alpha1.ApplicationSetTemplate{},
   437  		},
   438  	}
   439  	clusterGeneratorParams := map[string]interface{}{
   440  		"name": "production_01/west", "server": "https://production-01.example.com",
   441  	}
   442  	interpolatedGenerator, err = InterpolateGenerator(requestedGenerator, clusterGeneratorParams, false, nil)
   443  	if err != nil {
   444  		log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
   445  		return
   446  	}
   447  	assert.Equal(t, "production_01/west", interpolatedGenerator.Git.Files[0].Path)
   448  	assert.Equal(t, "https://production-01.example.com", interpolatedGenerator.Git.Files[1].Path)
   449  }
   450  
   451  func TestInterpolateGenerator_go(t *testing.T) {
   452  	requestedGenerator := &argov1alpha1.ApplicationSetGenerator{
   453  		Clusters: &argov1alpha1.ClusterGenerator{
   454  			Selector: metav1.LabelSelector{
   455  				MatchLabels: map[string]string{
   456  					"argocd.argoproj.io/secret-type": "cluster",
   457  					"path-basename":                  "{{base .path.path}}",
   458  					"path-zero":                      "{{index .path.segments 0}}",
   459  					"path-full":                      "{{.path.path}}",
   460  					"kubernetes.io/environment":      `{{default "foo" .my_label}}`,
   461  				}},
   462  		},
   463  	}
   464  	gitGeneratorParams := map[string]interface{}{
   465  		"path": map[string]interface{}{
   466  			"path":     "p1/p2/app3",
   467  			"segments": []string{"p1", "p2", "app3"},
   468  		},
   469  	}
   470  	interpolatedGenerator, err := InterpolateGenerator(requestedGenerator, gitGeneratorParams, true, nil)
   471  	require.NoError(t, err)
   472  	if err != nil {
   473  		log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
   474  		return
   475  	}
   476  	assert.Equal(t, "app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-basename"])
   477  	assert.Equal(t, "p1", interpolatedGenerator.Clusters.Selector.MatchLabels["path-zero"])
   478  	assert.Equal(t, "p1/p2/app3", interpolatedGenerator.Clusters.Selector.MatchLabels["path-full"])
   479  
   480  	fileNamePath := argov1alpha1.GitFileGeneratorItem{
   481  		Path: "{{.name}}",
   482  	}
   483  	fileServerPath := argov1alpha1.GitFileGeneratorItem{
   484  		Path: "{{.server}}",
   485  	}
   486  
   487  	requestedGenerator = &argov1alpha1.ApplicationSetGenerator{
   488  		Git: &argov1alpha1.GitGenerator{
   489  			Files:    append([]argov1alpha1.GitFileGeneratorItem{}, fileNamePath, fileServerPath),
   490  			Template: argov1alpha1.ApplicationSetTemplate{},
   491  		},
   492  	}
   493  	clusterGeneratorParams := map[string]interface{}{
   494  		"name": "production_01/west", "server": "https://production-01.example.com",
   495  	}
   496  	interpolatedGenerator, err = InterpolateGenerator(requestedGenerator, clusterGeneratorParams, true, nil)
   497  	if err != nil {
   498  		log.WithError(err).WithField("requestedGenerator", requestedGenerator).Error("error interpolating Generator")
   499  		return
   500  	}
   501  	assert.Equal(t, "production_01/west", interpolatedGenerator.Git.Files[0].Path)
   502  	assert.Equal(t, "https://production-01.example.com", interpolatedGenerator.Git.Files[1].Path)
   503  }
   504  
   505  func TestInterpolateGeneratorError(t *testing.T) {
   506  	type args struct {
   507  		requestedGenerator *argov1alpha1.ApplicationSetGenerator
   508  		params             map[string]interface{}
   509  		useGoTemplate      bool
   510  		goTemplateOptions  []string
   511  	}
   512  	tests := []struct {
   513  		name           string
   514  		args           args
   515  		want           argov1alpha1.ApplicationSetGenerator
   516  		expectedErrStr string
   517  	}{
   518  		{name: "Empty Gen", args: args{
   519  			requestedGenerator: nil,
   520  			params:             nil,
   521  			useGoTemplate:      false,
   522  			goTemplateOptions:  nil,
   523  		}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: "generator is empty"},
   524  		{name: "No Params", args: args{
   525  			requestedGenerator: &argov1alpha1.ApplicationSetGenerator{},
   526  			params:             map[string]interface{}{},
   527  			useGoTemplate:      false,
   528  			goTemplateOptions:  nil,
   529  		}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: ""},
   530  		{name: "Error templating", args: args{
   531  			requestedGenerator: &argov1alpha1.ApplicationSetGenerator{Git: &argov1alpha1.GitGenerator{
   532  				RepoURL:  "foo",
   533  				Files:    []argov1alpha1.GitFileGeneratorItem{{Path: "bar/"}},
   534  				Revision: "main",
   535  				Values: map[string]string{
   536  					"git_test":  "{{ toPrettyJson . }}",
   537  					"selection": "{{ default .override .test }}",
   538  					"resolved":  "{{ index .rmap (default .override .test) }}",
   539  				},
   540  			}},
   541  			params: map[string]interface{}{
   542  				"name":     "in-cluster",
   543  				"override": "foo",
   544  			},
   545  			useGoTemplate:     true,
   546  			goTemplateOptions: []string{},
   547  		}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: "failed to replace parameters in generator: failed to execute go template {{ index .rmap (default .override .test) }}: template: :1:3: executing \"\" at <index .rmap (default .override .test)>: error calling index: index of untyped nil"},
   548  	}
   549  	for _, tt := range tests {
   550  		t.Run(tt.name, func(t *testing.T) {
   551  			got, err := InterpolateGenerator(tt.args.requestedGenerator, tt.args.params, tt.args.useGoTemplate, tt.args.goTemplateOptions)
   552  			if tt.expectedErrStr != "" {
   553  				assert.EqualError(t, err, tt.expectedErrStr)
   554  			} else {
   555  				require.NoError(t, err)
   556  			}
   557  			assert.Equalf(t, tt.want, got, "InterpolateGenerator(%v, %v, %v, %v)", tt.args.requestedGenerator, tt.args.params, tt.args.useGoTemplate, tt.args.goTemplateOptions)
   558  		})
   559  	}
   560  }