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

     1  package generators
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	corev1 "k8s.io/api/core/v1"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    11  
    12  	"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider"
    13  	argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    14  )
    15  
    16  func TestSCMProviderGetSecretRef(t *testing.T) {
    17  	secret := &corev1.Secret{
    18  		ObjectMeta: metav1.ObjectMeta{Name: "test-secret", Namespace: "test"},
    19  		Data: map[string][]byte{
    20  			"my-token": []byte("secret"),
    21  		},
    22  	}
    23  	gen := &SCMProviderGenerator{client: fake.NewClientBuilder().WithObjects(secret).Build()}
    24  	ctx := context.Background()
    25  
    26  	cases := []struct {
    27  		name, namespace, token string
    28  		ref                    *argoprojiov1alpha1.SecretRef
    29  		hasError               bool
    30  	}{
    31  		{
    32  			name:      "valid ref",
    33  			ref:       &argoprojiov1alpha1.SecretRef{SecretName: "test-secret", Key: "my-token"},
    34  			namespace: "test",
    35  			token:     "secret",
    36  			hasError:  false,
    37  		},
    38  		{
    39  			name:      "nil ref",
    40  			ref:       nil,
    41  			namespace: "test",
    42  			token:     "",
    43  			hasError:  false,
    44  		},
    45  		{
    46  			name:      "wrong name",
    47  			ref:       &argoprojiov1alpha1.SecretRef{SecretName: "other", Key: "my-token"},
    48  			namespace: "test",
    49  			token:     "",
    50  			hasError:  true,
    51  		},
    52  		{
    53  			name:      "wrong key",
    54  			ref:       &argoprojiov1alpha1.SecretRef{SecretName: "test-secret", Key: "other-token"},
    55  			namespace: "test",
    56  			token:     "",
    57  			hasError:  true,
    58  		},
    59  		{
    60  			name:      "wrong namespace",
    61  			ref:       &argoprojiov1alpha1.SecretRef{SecretName: "test-secret", Key: "my-token"},
    62  			namespace: "other",
    63  			token:     "",
    64  			hasError:  true,
    65  		},
    66  	}
    67  
    68  	for _, c := range cases {
    69  		t.Run(c.name, func(t *testing.T) {
    70  			token, err := gen.getSecretRef(ctx, c.ref, c.namespace)
    71  			if c.hasError {
    72  				assert.NotNil(t, err)
    73  			} else {
    74  				assert.Nil(t, err)
    75  			}
    76  			assert.Equal(t, c.token, token)
    77  
    78  		})
    79  	}
    80  }
    81  
    82  func TestSCMProviderGenerateParams(t *testing.T) {
    83  	cases := []struct {
    84  		name          string
    85  		repos         []*scm_provider.Repository
    86  		values        map[string]string
    87  		expected      []map[string]interface{}
    88  		expectedError error
    89  	}{
    90  		{
    91  			name: "Multiple repos with labels",
    92  			repos: []*scm_provider.Repository{
    93  				{
    94  					Organization: "myorg",
    95  					Repository:   "repo1",
    96  					URL:          "git@github.com:myorg/repo1.git",
    97  					Branch:       "main",
    98  					SHA:          "0bc57212c3cbbec69d20b34c507284bd300def5b",
    99  					Labels:       []string{"prod", "staging"},
   100  				},
   101  				{
   102  					Organization: "myorg",
   103  					Repository:   "repo2",
   104  					URL:          "git@github.com:myorg/repo2.git",
   105  					Branch:       "main",
   106  					SHA:          "59d0",
   107  				},
   108  			},
   109  			expected: []map[string]interface{}{
   110  				{
   111  					"organization":     "myorg",
   112  					"repository":       "repo1",
   113  					"url":              "git@github.com:myorg/repo1.git",
   114  					"branch":           "main",
   115  					"branchNormalized": "main",
   116  					"sha":              "0bc57212c3cbbec69d20b34c507284bd300def5b",
   117  					"short_sha":        "0bc57212",
   118  					"short_sha_7":      "0bc5721",
   119  					"labels":           "prod,staging",
   120  				},
   121  				{
   122  					"organization":     "myorg",
   123  					"repository":       "repo2",
   124  					"url":              "git@github.com:myorg/repo2.git",
   125  					"branch":           "main",
   126  					"branchNormalized": "main",
   127  					"sha":              "59d0",
   128  					"short_sha":        "59d0",
   129  					"short_sha_7":      "59d0",
   130  					"labels":           "",
   131  				},
   132  			},
   133  		},
   134  		{
   135  			name: "Value interpolation",
   136  			repos: []*scm_provider.Repository{
   137  				{
   138  					Organization: "myorg",
   139  					Repository:   "repo3",
   140  					URL:          "git@github.com:myorg/repo3.git",
   141  					Branch:       "main",
   142  					SHA:          "0bc57212c3cbbec69d20b34c507284bd300def5b",
   143  					Labels:       []string{"prod", "staging"},
   144  				},
   145  			},
   146  			values: map[string]string{
   147  				"foo":                    "bar",
   148  				"should_i_force_push_to": "{{ branch }}?",
   149  			},
   150  			expected: []map[string]interface{}{
   151  				{
   152  					"organization":                  "myorg",
   153  					"repository":                    "repo3",
   154  					"url":                           "git@github.com:myorg/repo3.git",
   155  					"branch":                        "main",
   156  					"branchNormalized":              "main",
   157  					"sha":                           "0bc57212c3cbbec69d20b34c507284bd300def5b",
   158  					"short_sha":                     "0bc57212",
   159  					"short_sha_7":                   "0bc5721",
   160  					"labels":                        "prod,staging",
   161  					"values.foo":                    "bar",
   162  					"values.should_i_force_push_to": "main?",
   163  				},
   164  			},
   165  		},
   166  	}
   167  
   168  	for _, testCase := range cases {
   169  		testCaseCopy := testCase
   170  
   171  		t.Run(testCaseCopy.name, func(t *testing.T) {
   172  			t.Parallel()
   173  
   174  			mockProvider := &scm_provider.MockProvider{
   175  				Repos: testCaseCopy.repos,
   176  			}
   177  			scmGenerator := &SCMProviderGenerator{overrideProvider: mockProvider, enableSCMProviders: true}
   178  			applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
   179  				ObjectMeta: metav1.ObjectMeta{
   180  					Name: "set",
   181  				},
   182  				Spec: argoprojiov1alpha1.ApplicationSetSpec{
   183  					Generators: []argoprojiov1alpha1.ApplicationSetGenerator{{
   184  						SCMProvider: &argoprojiov1alpha1.SCMProviderGenerator{
   185  							Values: testCaseCopy.values,
   186  						},
   187  					}},
   188  				},
   189  			}
   190  
   191  			got, err := scmGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
   192  
   193  			if testCaseCopy.expectedError != nil {
   194  				assert.EqualError(t, err, testCaseCopy.expectedError.Error())
   195  			} else {
   196  				assert.NoError(t, err)
   197  				assert.Equal(t, testCaseCopy.expected, got)
   198  			}
   199  
   200  		})
   201  	}
   202  }
   203  
   204  func TestAllowedSCMProvider(t *testing.T) {
   205  	cases := []struct {
   206  		name           string
   207  		providerConfig *argoprojiov1alpha1.SCMProviderGenerator
   208  		expectedError  error
   209  	}{
   210  		{
   211  			name: "Error Github",
   212  			providerConfig: &argoprojiov1alpha1.SCMProviderGenerator{
   213  				Github: &argoprojiov1alpha1.SCMProviderGeneratorGithub{
   214  					API: "https://myservice.mynamespace.svc.cluster.local",
   215  				},
   216  			},
   217  			expectedError: &ErrDisallowedSCMProvider{},
   218  		},
   219  		{
   220  			name: "Error Gitlab",
   221  			providerConfig: &argoprojiov1alpha1.SCMProviderGenerator{
   222  				Gitlab: &argoprojiov1alpha1.SCMProviderGeneratorGitlab{
   223  					API: "https://myservice.mynamespace.svc.cluster.local",
   224  				},
   225  			},
   226  			expectedError: &ErrDisallowedSCMProvider{},
   227  		},
   228  		{
   229  			name: "Error Gitea",
   230  			providerConfig: &argoprojiov1alpha1.SCMProviderGenerator{
   231  				Gitea: &argoprojiov1alpha1.SCMProviderGeneratorGitea{
   232  					API: "https://myservice.mynamespace.svc.cluster.local",
   233  				},
   234  			},
   235  			expectedError: &ErrDisallowedSCMProvider{},
   236  		},
   237  		{
   238  			name: "Error Bitbucket",
   239  			providerConfig: &argoprojiov1alpha1.SCMProviderGenerator{
   240  				BitbucketServer: &argoprojiov1alpha1.SCMProviderGeneratorBitbucketServer{
   241  					API: "https://myservice.mynamespace.svc.cluster.local",
   242  				},
   243  			},
   244  			expectedError: &ErrDisallowedSCMProvider{},
   245  		},
   246  		{
   247  			name: "Error AzureDevops",
   248  			providerConfig: &argoprojiov1alpha1.SCMProviderGenerator{
   249  				AzureDevOps: &argoprojiov1alpha1.SCMProviderGeneratorAzureDevOps{
   250  					API: "https://myservice.mynamespace.svc.cluster.local",
   251  				},
   252  			},
   253  			expectedError: &ErrDisallowedSCMProvider{},
   254  		},
   255  	}
   256  
   257  	for _, testCase := range cases {
   258  		testCaseCopy := testCase
   259  
   260  		t.Run(testCaseCopy.name, func(t *testing.T) {
   261  			t.Parallel()
   262  
   263  			scmGenerator := &SCMProviderGenerator{
   264  				allowedSCMProviders: []string{
   265  					"github.myorg.com",
   266  					"gitlab.myorg.com",
   267  					"gitea.myorg.com",
   268  					"bitbucket.myorg.com",
   269  					"azuredevops.myorg.com",
   270  				},
   271  				enableSCMProviders: true,
   272  			}
   273  
   274  			applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
   275  				ObjectMeta: metav1.ObjectMeta{
   276  					Name: "set",
   277  				},
   278  				Spec: argoprojiov1alpha1.ApplicationSetSpec{
   279  					Generators: []argoprojiov1alpha1.ApplicationSetGenerator{{
   280  						SCMProvider: testCaseCopy.providerConfig,
   281  					}},
   282  				},
   283  			}
   284  
   285  			_, err := scmGenerator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
   286  
   287  			assert.Error(t, err, "Must return an error")
   288  			assert.ErrorAs(t, err, testCaseCopy.expectedError)
   289  		})
   290  	}
   291  }
   292  
   293  func TestSCMProviderDisabled_SCMGenerator(t *testing.T) {
   294  	generator := &SCMProviderGenerator{enableSCMProviders: false}
   295  
   296  	applicationSetInfo := argoprojiov1alpha1.ApplicationSet{
   297  		ObjectMeta: metav1.ObjectMeta{
   298  			Name: "set",
   299  		},
   300  		Spec: argoprojiov1alpha1.ApplicationSetSpec{
   301  			Generators: []argoprojiov1alpha1.ApplicationSetGenerator{{
   302  				SCMProvider: &argoprojiov1alpha1.SCMProviderGenerator{
   303  					Github: &argoprojiov1alpha1.SCMProviderGeneratorGithub{
   304  						API: "https://myservice.mynamespace.svc.cluster.local",
   305  					},
   306  				},
   307  			}},
   308  		},
   309  	}
   310  
   311  	_, err := generator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo)
   312  	assert.ErrorIs(t, err, ErrSCMProvidersDisabled)
   313  }