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

     1  package webhook
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"os"
    11  	"path/filepath"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/mock"
    17  	corev1 "k8s.io/api/core/v1"
    18  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    19  	"k8s.io/apimachinery/pkg/runtime"
    20  	kubefake "k8s.io/client-go/kubernetes/fake"
    21  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    22  
    23  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    24  
    25  	"github.com/argoproj/argo-cd/v2/applicationset/generators"
    26  	"github.com/argoproj/argo-cd/v2/applicationset/services/scm_provider"
    27  	"github.com/argoproj/argo-cd/v2/common"
    28  	"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
    29  	argosettings "github.com/argoproj/argo-cd/v2/util/settings"
    30  )
    31  
    32  type generatorMock struct {
    33  	mock.Mock
    34  }
    35  
    36  func (g *generatorMock) GetTemplate(appSetGenerator *v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate {
    37  	return &v1alpha1.ApplicationSetTemplate{}
    38  }
    39  
    40  func (g *generatorMock) GenerateParams(appSetGenerator *v1alpha1.ApplicationSetGenerator, _ *v1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
    41  	return []map[string]interface{}{}, nil
    42  }
    43  
    44  func (g *generatorMock) GetRequeueAfter(appSetGenerator *v1alpha1.ApplicationSetGenerator) time.Duration {
    45  	d, _ := time.ParseDuration("10s")
    46  	return d
    47  }
    48  
    49  func TestWebhookHandler(t *testing.T) {
    50  	tt := []struct {
    51  		desc               string
    52  		headerKey          string
    53  		headerValue        string
    54  		effectedAppSets    []string
    55  		payloadFile        string
    56  		expectedStatusCode int
    57  		expectedRefresh    bool
    58  	}{
    59  		{
    60  			desc:               "WebHook from a GitHub repository via Commit",
    61  			headerKey:          "X-GitHub-Event",
    62  			headerValue:        "push",
    63  			payloadFile:        "github-commit-event.json",
    64  			effectedAppSets:    []string{"git-github", "matrix-git-github", "merge-git-github", "matrix-scm-git-github", "matrix-nested-git-github", "merge-nested-git-github", "plugin", "matrix-pull-request-github-plugin"},
    65  			expectedStatusCode: http.StatusOK,
    66  			expectedRefresh:    true,
    67  		},
    68  		{
    69  			desc:               "WebHook from a GitHub repository via Commit to branch",
    70  			headerKey:          "X-GitHub-Event",
    71  			headerValue:        "push",
    72  			payloadFile:        "github-commit-branch-event.json",
    73  			effectedAppSets:    []string{"git-github", "plugin", "matrix-pull-request-github-plugin"},
    74  			expectedStatusCode: http.StatusOK,
    75  			expectedRefresh:    true,
    76  		},
    77  		{
    78  			desc:               "WebHook from a GitHub ping event",
    79  			headerKey:          "X-GitHub-Event",
    80  			headerValue:        "ping",
    81  			payloadFile:        "github-ping-event.json",
    82  			effectedAppSets:    []string{"git-github", "plugin"},
    83  			expectedStatusCode: http.StatusOK,
    84  			expectedRefresh:    false,
    85  		},
    86  		{
    87  			desc:               "WebHook from a GitLab repository via Commit",
    88  			headerKey:          "X-Gitlab-Event",
    89  			headerValue:        "Push Hook",
    90  			payloadFile:        "gitlab-event.json",
    91  			effectedAppSets:    []string{"git-gitlab", "plugin", "matrix-pull-request-github-plugin"},
    92  			expectedStatusCode: http.StatusOK,
    93  			expectedRefresh:    true,
    94  		},
    95  		{
    96  			desc:               "WebHook with an unknown event",
    97  			headerKey:          "X-Random-Event",
    98  			headerValue:        "Push Hook",
    99  			payloadFile:        "gitlab-event.json",
   100  			effectedAppSets:    []string{"git-gitlab", "plugin"},
   101  			expectedStatusCode: http.StatusBadRequest,
   102  			expectedRefresh:    false,
   103  		},
   104  		{
   105  			desc:               "WebHook with an invalid event",
   106  			headerKey:          "X-Random-Event",
   107  			headerValue:        "Push Hook",
   108  			payloadFile:        "invalid-event.json",
   109  			effectedAppSets:    []string{"git-gitlab", "plugin"},
   110  			expectedStatusCode: http.StatusBadRequest,
   111  			expectedRefresh:    false,
   112  		},
   113  		{
   114  			desc:               "WebHook from a GitHub repository via pull_request opened event",
   115  			headerKey:          "X-GitHub-Event",
   116  			headerValue:        "pull_request",
   117  			payloadFile:        "github-pull-request-opened-event.json",
   118  			effectedAppSets:    []string{"pull-request-github", "matrix-pull-request-github", "matrix-scm-pull-request-github", "merge-pull-request-github", "plugin", "matrix-pull-request-github-plugin"},
   119  			expectedStatusCode: http.StatusOK,
   120  			expectedRefresh:    true,
   121  		},
   122  		{
   123  			desc:               "WebHook from a GitHub repository via pull_request assigned event",
   124  			headerKey:          "X-GitHub-Event",
   125  			headerValue:        "pull_request",
   126  			payloadFile:        "github-pull-request-assigned-event.json",
   127  			effectedAppSets:    []string{"pull-request-github", "matrix-pull-request-github", "matrix-scm-pull-request-github", "merge-pull-request-github", "plugin", "matrix-pull-request-github-plugin"},
   128  			expectedStatusCode: http.StatusOK,
   129  			expectedRefresh:    false,
   130  		},
   131  		{
   132  			desc:               "WebHook from a GitHub repository via pull_request labeled event",
   133  			headerKey:          "X-GitHub-Event",
   134  			headerValue:        "pull_request",
   135  			payloadFile:        "github-pull-request-labeled-event.json",
   136  			effectedAppSets:    []string{"pull-request-github", "matrix-pull-request-github", "matrix-scm-pull-request-github", "merge-pull-request-github", "plugin", "matrix-pull-request-github-plugin"},
   137  			expectedStatusCode: http.StatusOK,
   138  			expectedRefresh:    true,
   139  		},
   140  		{
   141  			desc:               "WebHook from a GitLab repository via open merge request event",
   142  			headerKey:          "X-Gitlab-Event",
   143  			headerValue:        "Merge Request Hook",
   144  			payloadFile:        "gitlab-merge-request-open-event.json",
   145  			effectedAppSets:    []string{"pull-request-gitlab", "plugin", "matrix-pull-request-github-plugin"},
   146  			expectedStatusCode: http.StatusOK,
   147  			expectedRefresh:    true,
   148  		},
   149  		{
   150  			desc:               "WebHook from a GitLab repository via approval merge request event",
   151  			headerKey:          "X-Gitlab-Event",
   152  			headerValue:        "Merge Request Hook",
   153  			payloadFile:        "gitlab-merge-request-approval-event.json",
   154  			effectedAppSets:    []string{"pull-request-gitlab", "plugin"},
   155  			expectedStatusCode: http.StatusOK,
   156  			expectedRefresh:    false,
   157  		},
   158  		{
   159  			desc:               "WebHook from a Azure DevOps repository via Commit",
   160  			headerKey:          "X-Vss-Activityid",
   161  			headerValue:        "Push Hook",
   162  			payloadFile:        "azuredevops-push.json",
   163  			effectedAppSets:    []string{"git-azure-devops", "plugin", "matrix-pull-request-github-plugin"},
   164  			expectedStatusCode: http.StatusOK,
   165  			expectedRefresh:    true,
   166  		},
   167  		{
   168  			desc:               "WebHook from a Azure DevOps repository via pull request event",
   169  			headerKey:          "X-Vss-Activityid",
   170  			headerValue:        "Pull Request Hook",
   171  			payloadFile:        "azuredevops-pull-request.json",
   172  			effectedAppSets:    []string{"pull-request-azure-devops", "plugin", "matrix-pull-request-github-plugin"},
   173  			expectedStatusCode: http.StatusOK,
   174  			expectedRefresh:    true,
   175  		},
   176  	}
   177  
   178  	namespace := "test"
   179  	fakeClient := newFakeClient(namespace)
   180  	scheme := runtime.NewScheme()
   181  	err := v1alpha1.AddToScheme(scheme)
   182  	assert.Nil(t, err)
   183  	err = v1alpha1.AddToScheme(scheme)
   184  	assert.Nil(t, err)
   185  
   186  	for _, test := range tt {
   187  		t.Run(test.desc, func(t *testing.T) {
   188  			fc := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
   189  				fakeAppWithGitGenerator("git-github", namespace, "https://github.com/org/repo"),
   190  				fakeAppWithGitGenerator("git-gitlab", namespace, "https://gitlab/group/name"),
   191  				fakeAppWithGitGenerator("git-azure-devops", namespace, "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git"),
   192  				fakeAppWithGithubPullRequestGenerator("pull-request-github", namespace, "CodErTOcat", "Hello-World"),
   193  				fakeAppWithGitlabPullRequestGenerator("pull-request-gitlab", namespace, "100500"),
   194  				fakeAppWithAzureDevOpsPullRequestGenerator("pull-request-azure-devops", namespace, "DefaultCollection", "Fabrikam"),
   195  				fakeAppWithPluginGenerator("plugin", namespace),
   196  				fakeAppWithMatrixAndGitGenerator("matrix-git-github", namespace, "https://github.com/org/repo"),
   197  				fakeAppWithMatrixAndPullRequestGenerator("matrix-pull-request-github", namespace, "Codertocat", "Hello-World"),
   198  				fakeAppWithMatrixAndScmWithGitGenerator("matrix-scm-git-github", namespace, "org"),
   199  				fakeAppWithMatrixAndScmWithPullRequestGenerator("matrix-scm-pull-request-github", namespace, "Codertocat"),
   200  				fakeAppWithMatrixAndNestedGitGenerator("matrix-nested-git-github", namespace, "https://github.com/org/repo"),
   201  				fakeAppWithMatrixAndPullRequestGeneratorWithPluginGenerator("matrix-pull-request-github-plugin", namespace, "coDErtoCat", "HeLLO-WorLD", "plugin-cm"),
   202  				fakeAppWithMergeAndGitGenerator("merge-git-github", namespace, "https://github.com/org/repo"),
   203  				fakeAppWithMergeAndPullRequestGenerator("merge-pull-request-github", namespace, "Codertocat", "Hello-World"),
   204  				fakeAppWithMergeAndNestedGitGenerator("merge-nested-git-github", namespace, "https://github.com/org/repo"),
   205  			).Build()
   206  			set := argosettings.NewSettingsManager(context.TODO(), fakeClient, namespace)
   207  			h, err := NewWebhookHandler(namespace, set, fc, mockGenerators())
   208  			assert.Nil(t, err)
   209  
   210  			req := httptest.NewRequest(http.MethodPost, "/api/webhook", nil)
   211  			req.Header.Set(test.headerKey, test.headerValue)
   212  			eventJSON, err := os.ReadFile(filepath.Join("testdata", test.payloadFile))
   213  			assert.NoError(t, err)
   214  			req.Body = io.NopCloser(bytes.NewReader(eventJSON))
   215  			w := httptest.NewRecorder()
   216  
   217  			h.Handler(w, req)
   218  			assert.Equal(t, w.Code, test.expectedStatusCode)
   219  
   220  			list := &v1alpha1.ApplicationSetList{}
   221  			err = fc.List(context.TODO(), list)
   222  			assert.Nil(t, err)
   223  			effectedAppSetsAsExpected := make(map[string]bool)
   224  			for _, appSetName := range test.effectedAppSets {
   225  				effectedAppSetsAsExpected[appSetName] = false
   226  			}
   227  			for i := range list.Items {
   228  				gotAppSet := &list.Items[i]
   229  				if _, isEffected := effectedAppSetsAsExpected[gotAppSet.Name]; isEffected {
   230  					if expected, got := test.expectedRefresh, gotAppSet.RefreshRequired(); expected != got {
   231  						t.Errorf("unexpected RefreshRequired() for appset '%s' expect: %v got: %v", gotAppSet.Name, expected, got)
   232  					}
   233  					effectedAppSetsAsExpected[gotAppSet.Name] = true
   234  				} else {
   235  					assert.False(t, gotAppSet.RefreshRequired())
   236  				}
   237  			}
   238  			for appSetName, checked := range effectedAppSetsAsExpected {
   239  				assert.True(t, checked, "appset %s not found", appSetName)
   240  			}
   241  		})
   242  	}
   243  }
   244  
   245  func mockGenerators() map[string]generators.Generator {
   246  	// generatorMockList := generatorMock{}
   247  	generatorMockGit := &generatorMock{}
   248  	generatorMockPR := &generatorMock{}
   249  	generatorMockPlugin := &generatorMock{}
   250  	mockSCMProvider := &scm_provider.MockProvider{
   251  		Repos: []*scm_provider.Repository{
   252  			{
   253  				Organization: "myorg",
   254  				Repository:   "repo1",
   255  				URL:          "git@github.com:org/repo.git",
   256  				Branch:       "main",
   257  				SHA:          "0bc57212c3cbbec69d20b34c507284bd300def5b",
   258  			},
   259  			{
   260  				Organization: "Codertocat",
   261  				Repository:   "Hello-World",
   262  				URL:          "git@github.com:Codertocat/Hello-World.git",
   263  				Branch:       "main",
   264  				SHA:          "59d0",
   265  			},
   266  		},
   267  	}
   268  	generatorMockSCM := generators.NewTestSCMProviderGenerator(mockSCMProvider)
   269  
   270  	terminalMockGenerators := map[string]generators.Generator{
   271  		"List":        generators.NewListGenerator(),
   272  		"Git":         generatorMockGit,
   273  		"SCMProvider": generatorMockSCM,
   274  		"PullRequest": generatorMockPR,
   275  		"Plugin":      generatorMockPlugin,
   276  	}
   277  
   278  	nestedGenerators := map[string]generators.Generator{
   279  		"List":        terminalMockGenerators["List"],
   280  		"Git":         terminalMockGenerators["Git"],
   281  		"SCMProvider": terminalMockGenerators["SCMProvider"],
   282  		"PullRequest": terminalMockGenerators["PullRequest"],
   283  		"Plugin":      terminalMockGenerators["Plugin"],
   284  		"Matrix":      generators.NewMatrixGenerator(terminalMockGenerators),
   285  		"Merge":       generators.NewMergeGenerator(terminalMockGenerators),
   286  	}
   287  
   288  	return map[string]generators.Generator{
   289  		"List":        terminalMockGenerators["List"],
   290  		"Git":         terminalMockGenerators["Git"],
   291  		"SCMProvider": terminalMockGenerators["SCMProvider"],
   292  		"PullRequest": terminalMockGenerators["PullRequest"],
   293  		"Plugin":      terminalMockGenerators["Plugin"],
   294  		"Matrix":      generators.NewMatrixGenerator(nestedGenerators),
   295  		"Merge":       generators.NewMergeGenerator(nestedGenerators),
   296  	}
   297  }
   298  
   299  func TestGenRevisionHasChanged(t *testing.T) {
   300  	assert.True(t, genRevisionHasChanged(&v1alpha1.GitGenerator{}, "master", true))
   301  	assert.False(t, genRevisionHasChanged(&v1alpha1.GitGenerator{}, "master", false))
   302  
   303  	assert.True(t, genRevisionHasChanged(&v1alpha1.GitGenerator{Revision: "dev"}, "dev", true))
   304  	assert.False(t, genRevisionHasChanged(&v1alpha1.GitGenerator{Revision: "dev"}, "master", false))
   305  
   306  	assert.True(t, genRevisionHasChanged(&v1alpha1.GitGenerator{Revision: "refs/heads/dev"}, "dev", true))
   307  	assert.False(t, genRevisionHasChanged(&v1alpha1.GitGenerator{Revision: "refs/heads/dev"}, "master", false))
   308  }
   309  
   310  func fakeAppWithGitGenerator(name, namespace, repo string) *v1alpha1.ApplicationSet {
   311  	return &v1alpha1.ApplicationSet{
   312  		ObjectMeta: metav1.ObjectMeta{
   313  			Name:      name,
   314  			Namespace: namespace,
   315  		},
   316  		Spec: v1alpha1.ApplicationSetSpec{
   317  			Generators: []v1alpha1.ApplicationSetGenerator{
   318  				{
   319  					Git: &v1alpha1.GitGenerator{
   320  						RepoURL:  repo,
   321  						Revision: "master",
   322  					},
   323  				},
   324  			},
   325  		},
   326  	}
   327  }
   328  
   329  func fakeAppWithGitlabPullRequestGenerator(name, namespace, projectId string) *v1alpha1.ApplicationSet {
   330  	return &v1alpha1.ApplicationSet{
   331  		ObjectMeta: metav1.ObjectMeta{
   332  			Name:      name,
   333  			Namespace: namespace,
   334  		},
   335  		Spec: v1alpha1.ApplicationSetSpec{
   336  			Generators: []v1alpha1.ApplicationSetGenerator{
   337  				{
   338  					PullRequest: &v1alpha1.PullRequestGenerator{
   339  						GitLab: &v1alpha1.PullRequestGeneratorGitLab{
   340  							Project: projectId,
   341  						},
   342  					},
   343  				},
   344  			},
   345  		},
   346  	}
   347  }
   348  
   349  func fakeAppWithGithubPullRequestGenerator(name, namespace, owner, repo string) *v1alpha1.ApplicationSet {
   350  	return &v1alpha1.ApplicationSet{
   351  		ObjectMeta: metav1.ObjectMeta{
   352  			Name:      name,
   353  			Namespace: namespace,
   354  		},
   355  		Spec: v1alpha1.ApplicationSetSpec{
   356  			Generators: []v1alpha1.ApplicationSetGenerator{
   357  				{
   358  					PullRequest: &v1alpha1.PullRequestGenerator{
   359  						Github: &v1alpha1.PullRequestGeneratorGithub{
   360  							Owner: owner,
   361  							Repo:  repo,
   362  						},
   363  					},
   364  				},
   365  			},
   366  		},
   367  	}
   368  }
   369  
   370  func fakeAppWithAzureDevOpsPullRequestGenerator(name, namespace, project, repo string) *v1alpha1.ApplicationSet {
   371  	return &v1alpha1.ApplicationSet{
   372  		ObjectMeta: metav1.ObjectMeta{
   373  			Name:      name,
   374  			Namespace: namespace,
   375  		},
   376  		Spec: v1alpha1.ApplicationSetSpec{
   377  			Generators: []v1alpha1.ApplicationSetGenerator{
   378  				{
   379  					PullRequest: &v1alpha1.PullRequestGenerator{
   380  						AzureDevOps: &v1alpha1.PullRequestGeneratorAzureDevOps{
   381  							Project: project,
   382  							Repo:    repo,
   383  						},
   384  					},
   385  				},
   386  			},
   387  		},
   388  	}
   389  }
   390  
   391  func fakeAppWithMatrixAndGitGenerator(name, namespace, repo string) *v1alpha1.ApplicationSet {
   392  	return &v1alpha1.ApplicationSet{
   393  		ObjectMeta: metav1.ObjectMeta{
   394  			Name:      name,
   395  			Namespace: namespace,
   396  		},
   397  		Spec: v1alpha1.ApplicationSetSpec{
   398  			Generators: []v1alpha1.ApplicationSetGenerator{
   399  				{
   400  					Matrix: &v1alpha1.MatrixGenerator{
   401  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   402  							{
   403  								List: &v1alpha1.ListGenerator{},
   404  							},
   405  							{
   406  								Git: &v1alpha1.GitGenerator{
   407  									RepoURL: repo,
   408  								},
   409  							},
   410  						},
   411  					},
   412  				},
   413  			},
   414  		},
   415  	}
   416  }
   417  
   418  func fakeAppWithMatrixAndPullRequestGenerator(name, namespace, owner, repo string) *v1alpha1.ApplicationSet {
   419  	return &v1alpha1.ApplicationSet{
   420  		ObjectMeta: metav1.ObjectMeta{
   421  			Name:      name,
   422  			Namespace: namespace,
   423  		},
   424  		Spec: v1alpha1.ApplicationSetSpec{
   425  			Generators: []v1alpha1.ApplicationSetGenerator{
   426  				{
   427  					Matrix: &v1alpha1.MatrixGenerator{
   428  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   429  							{
   430  								List: &v1alpha1.ListGenerator{},
   431  							},
   432  							{
   433  								PullRequest: &v1alpha1.PullRequestGenerator{
   434  									Github: &v1alpha1.PullRequestGeneratorGithub{
   435  										Owner: owner,
   436  										Repo:  repo,
   437  									},
   438  								},
   439  							},
   440  						},
   441  					},
   442  				},
   443  			},
   444  		},
   445  	}
   446  }
   447  
   448  func fakeAppWithMatrixAndScmWithGitGenerator(name, namespace, owner string) *v1alpha1.ApplicationSet {
   449  	return &v1alpha1.ApplicationSet{
   450  		ObjectMeta: metav1.ObjectMeta{
   451  			Name:      name,
   452  			Namespace: namespace,
   453  		},
   454  		Spec: v1alpha1.ApplicationSetSpec{
   455  			Generators: []v1alpha1.ApplicationSetGenerator{
   456  				{
   457  					Matrix: &v1alpha1.MatrixGenerator{
   458  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   459  							{
   460  								SCMProvider: &v1alpha1.SCMProviderGenerator{
   461  									CloneProtocol: "ssh",
   462  									Github: &v1alpha1.SCMProviderGeneratorGithub{
   463  										Organization: owner,
   464  									},
   465  								},
   466  							},
   467  							{
   468  								Git: &v1alpha1.GitGenerator{
   469  									RepoURL: "{{ url }}",
   470  								},
   471  							},
   472  						},
   473  					},
   474  				},
   475  			},
   476  		},
   477  	}
   478  }
   479  
   480  func fakeAppWithMatrixAndScmWithPullRequestGenerator(name, namespace, owner string) *v1alpha1.ApplicationSet {
   481  	return &v1alpha1.ApplicationSet{
   482  		ObjectMeta: metav1.ObjectMeta{
   483  			Name:      name,
   484  			Namespace: namespace,
   485  		},
   486  		Spec: v1alpha1.ApplicationSetSpec{
   487  			Generators: []v1alpha1.ApplicationSetGenerator{
   488  				{
   489  					Matrix: &v1alpha1.MatrixGenerator{
   490  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   491  							{
   492  								SCMProvider: &v1alpha1.SCMProviderGenerator{
   493  									CloneProtocol: "https",
   494  									Github: &v1alpha1.SCMProviderGeneratorGithub{
   495  										Organization: owner,
   496  									},
   497  								},
   498  							},
   499  							{
   500  								PullRequest: &v1alpha1.PullRequestGenerator{
   501  									Github: &v1alpha1.PullRequestGeneratorGithub{
   502  										Owner: "{{ organization }}",
   503  										Repo:  "{{ repository }}",
   504  									},
   505  								},
   506  							},
   507  						},
   508  					},
   509  				},
   510  			},
   511  		},
   512  	}
   513  }
   514  
   515  func fakeAppWithMatrixAndNestedGitGenerator(name, namespace, repo string) *v1alpha1.ApplicationSet {
   516  	return &v1alpha1.ApplicationSet{
   517  		ObjectMeta: metav1.ObjectMeta{
   518  			Name:      name,
   519  			Namespace: namespace,
   520  		},
   521  		Spec: v1alpha1.ApplicationSetSpec{
   522  			Generators: []v1alpha1.ApplicationSetGenerator{
   523  				{
   524  					Matrix: &v1alpha1.MatrixGenerator{
   525  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   526  							{
   527  								List: &v1alpha1.ListGenerator{},
   528  							},
   529  							{
   530  								Matrix: &apiextensionsv1.JSON{
   531  									Raw: []byte(fmt.Sprintf(`{
   532  										"Generators": [
   533  											{
   534  												"List": {
   535  													"Elements": [
   536  														{
   537  															"repository": "%s"
   538  														}
   539  													]
   540  												}
   541  											},
   542  											{
   543  												"Git": {
   544  													"RepoURL": "{{ repository }}"
   545  												}
   546  											}
   547  										]
   548  									}`, repo)),
   549  								},
   550  							},
   551  						},
   552  					},
   553  				},
   554  			},
   555  		},
   556  	}
   557  }
   558  
   559  func fakeAppWithMergeAndGitGenerator(name, namespace, repo string) *v1alpha1.ApplicationSet {
   560  	return &v1alpha1.ApplicationSet{
   561  		ObjectMeta: metav1.ObjectMeta{
   562  			Name:      name,
   563  			Namespace: namespace,
   564  		},
   565  		Spec: v1alpha1.ApplicationSetSpec{
   566  			Generators: []v1alpha1.ApplicationSetGenerator{
   567  				{
   568  					Merge: &v1alpha1.MergeGenerator{
   569  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   570  							{
   571  								Git: &v1alpha1.GitGenerator{
   572  									RepoURL: repo,
   573  								},
   574  							},
   575  						},
   576  					},
   577  				},
   578  			},
   579  		},
   580  	}
   581  }
   582  
   583  func fakeAppWithMergeAndPullRequestGenerator(name, namespace, owner, repo string) *v1alpha1.ApplicationSet {
   584  	return &v1alpha1.ApplicationSet{
   585  		ObjectMeta: metav1.ObjectMeta{
   586  			Name:      name,
   587  			Namespace: namespace,
   588  		},
   589  		Spec: v1alpha1.ApplicationSetSpec{
   590  			Generators: []v1alpha1.ApplicationSetGenerator{
   591  				{
   592  					Merge: &v1alpha1.MergeGenerator{
   593  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   594  							{
   595  								PullRequest: &v1alpha1.PullRequestGenerator{
   596  									Github: &v1alpha1.PullRequestGeneratorGithub{
   597  										Owner: owner,
   598  										Repo:  repo,
   599  									},
   600  								},
   601  							},
   602  						},
   603  					},
   604  				},
   605  			},
   606  		},
   607  	}
   608  }
   609  
   610  func fakeAppWithMergeAndNestedGitGenerator(name, namespace, repo string) *v1alpha1.ApplicationSet {
   611  	return &v1alpha1.ApplicationSet{
   612  		ObjectMeta: metav1.ObjectMeta{
   613  			Name:      name,
   614  			Namespace: namespace,
   615  		},
   616  		Spec: v1alpha1.ApplicationSetSpec{
   617  			Generators: []v1alpha1.ApplicationSetGenerator{
   618  				{
   619  					Merge: &v1alpha1.MergeGenerator{
   620  						MergeKeys: []string{
   621  							"server",
   622  						},
   623  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   624  							{
   625  								List: &v1alpha1.ListGenerator{},
   626  							},
   627  							{
   628  								Merge: &apiextensionsv1.JSON{
   629  									Raw: []byte(fmt.Sprintf(`{
   630  										"MergeKeys": ["server"],
   631  										"Generators": [
   632  											{
   633  												"List": {}
   634  											},
   635  											{
   636  												"Git": {
   637  													"RepoURL": "%s"
   638  												}
   639  											}
   640  										]
   641  									}`, repo)),
   642  								},
   643  							},
   644  						},
   645  					},
   646  				},
   647  			},
   648  		},
   649  	}
   650  }
   651  
   652  func fakeAppWithPluginGenerator(name, namespace string) *v1alpha1.ApplicationSet {
   653  	return &v1alpha1.ApplicationSet{
   654  		ObjectMeta: metav1.ObjectMeta{
   655  			Name:      name,
   656  			Namespace: namespace,
   657  		},
   658  		Spec: v1alpha1.ApplicationSetSpec{
   659  			Generators: []v1alpha1.ApplicationSetGenerator{
   660  				{
   661  					Plugin: &v1alpha1.PluginGenerator{
   662  						ConfigMapRef: v1alpha1.PluginConfigMapRef{
   663  							Name: "test",
   664  						},
   665  					},
   666  				},
   667  			},
   668  		},
   669  	}
   670  }
   671  
   672  func fakeAppWithMatrixAndPullRequestGeneratorWithPluginGenerator(name, namespace, owner, repo, configmapName string) *v1alpha1.ApplicationSet {
   673  	return &v1alpha1.ApplicationSet{
   674  		ObjectMeta: metav1.ObjectMeta{
   675  			Name:      name,
   676  			Namespace: namespace,
   677  		},
   678  		Spec: v1alpha1.ApplicationSetSpec{
   679  			Generators: []v1alpha1.ApplicationSetGenerator{
   680  				{
   681  					Matrix: &v1alpha1.MatrixGenerator{
   682  						Generators: []v1alpha1.ApplicationSetNestedGenerator{
   683  							{
   684  								PullRequest: &v1alpha1.PullRequestGenerator{
   685  									Github: &v1alpha1.PullRequestGeneratorGithub{
   686  										Owner: owner,
   687  										Repo:  repo,
   688  									},
   689  								},
   690  							},
   691  							{
   692  								Plugin: &v1alpha1.PluginGenerator{
   693  									ConfigMapRef: v1alpha1.PluginConfigMapRef{
   694  										Name: configmapName,
   695  									},
   696  								},
   697  							},
   698  						},
   699  					},
   700  				},
   701  			},
   702  		},
   703  	}
   704  }
   705  
   706  func newFakeClient(ns string) *kubefake.Clientset {
   707  	s := runtime.NewScheme()
   708  	s.AddKnownTypes(v1alpha1.SchemeGroupVersion, &v1alpha1.ApplicationSet{})
   709  	return kubefake.NewSimpleClientset(&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "argocd-cm", Namespace: ns, Labels: map[string]string{
   710  		"app.kubernetes.io/part-of": "argocd",
   711  	}}}, &corev1.Secret{
   712  		ObjectMeta: metav1.ObjectMeta{
   713  			Name:      common.ArgoCDSecretName,
   714  			Namespace: ns,
   715  			Labels: map[string]string{
   716  				"app.kubernetes.io/part-of": "argocd",
   717  			},
   718  		},
   719  		Data: map[string][]byte{
   720  			"server.secretkey": nil,
   721  		},
   722  	})
   723  }