diff --git a/applicationset/generators/git.go b/applicationset/generators/git.go index 2919f104eba04..d12f846f174e8 100644 --- a/applicationset/generators/git.go +++ b/applicationset/generators/git.go @@ -162,8 +162,10 @@ func (g *GitGenerator) generateParamsFromGitFile(filePath string, fileContent [] } params["path"] = path.Dir(filePath) params["path.basename"] = path.Base(params["path"]) + params["path.filename"] = path.Base(filePath) params["path.basenameNormalized"] = sanitizeName(path.Base(params["path"])) - for k, v := range strings.Split(strings.TrimSuffix(params["path"], params["path.basename"]), "/") { + params["path.filenameNormalized"] = sanitizeName(path.Base(params["path.filename"])) + for k, v := range strings.Split(params["path"], "/") { if len(v) > 0 { params["path["+strconv.Itoa(k)+"]"] = v } @@ -213,7 +215,7 @@ func (g *GitGenerator) generateParamsFromApps(requestedApps []string, _ *argopro params["path"] = a params["path.basename"] = path.Base(a) params["path.basenameNormalized"] = sanitizeName(path.Base(a)) - for k, v := range strings.Split(strings.TrimSuffix(params["path"], params["path.basename"]), "/") { + for k, v := range strings.Split(params["path"], "/") { if len(v) > 0 { params["path["+strconv.Itoa(k)+"]"] = v } diff --git a/applicationset/generators/git_test.go b/applicationset/generators/git_test.go index 2f96981a7d6d5..18dcd20538704 100644 --- a/applicationset/generators/git_test.go +++ b/applicationset/generators/git_test.go @@ -47,6 +47,28 @@ func (a argoCDServiceMock) GetDirectories(ctx context.Context, repoURL string, r return args.Get(0).([]string), args.Error(1) } +func Test_generateParamsFromGitFile(t *testing.T) { + params, err := (*GitGenerator)(nil).generateParamsFromGitFile("path/dir/file_name.yaml", []byte(` +foo: + bar: baz +`)) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, []map[string]string{ + { + "foo.bar": "baz", + "path": "path/dir", + "path.basename": "dir", + "path.filename": "file_name.yaml", + "path.basenameNormalized": "dir", + "path.filenameNormalized": "file-name.yaml", + "path[0]": "path", + "path[1]": "dir", + }, + }, params) +} + func TestGitGenerateParamsFromDirectories(t *testing.T) { cases := []struct { @@ -68,9 +90,9 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) { }, repoError: nil, expected: []map[string]string{ - {"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1"}, - {"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2"}, - {"path": "app_3", "path.basename": "app_3", "path.basenameNormalized": "app-3"}, + {"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1", "path[0]": "app1"}, + {"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2", "path[0]": "app2"}, + {"path": "app_3", "path.basename": "app_3", "path.basenameNormalized": "app-3", "path[0]": "app_3"}, }, expectedError: nil, }, @@ -85,8 +107,8 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) { }, repoError: nil, expected: []map[string]string{ - {"path": "p1/app2", "path.basename": "app2", "path[0]": "p1", "path.basenameNormalized": "app2"}, - {"path": "p1/p2/app3", "path.basename": "app3", "path[0]": "p1", "path[1]": "p2", "path.basenameNormalized": "app3"}, + {"path": "p1/app2", "path.basename": "app2", "path[0]": "p1", "path[1]": "app2", "path.basenameNormalized": "app2"}, + {"path": "p1/p2/app3", "path.basename": "app3", "path[0]": "p1", "path[1]": "p2", "path[2]": "app3", "path.basenameNormalized": "app3"}, }, expectedError: nil, }, @@ -102,9 +124,9 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) { }, repoError: nil, expected: []map[string]string{ - {"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1"}, - {"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2"}, - {"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path.basenameNormalized": "app3"}, + {"path": "app1", "path.basename": "app1", "path[0]": "app1", "path.basenameNormalized": "app1"}, + {"path": "app2", "path.basename": "app2", "path[0]": "app2", "path.basenameNormalized": "app2"}, + {"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path[1]": "app3", "path.basenameNormalized": "app3"}, }, expectedError: nil, }, @@ -120,9 +142,9 @@ func TestGitGenerateParamsFromDirectories(t *testing.T) { }, repoError: nil, expected: []map[string]string{ - {"path": "app1", "path.basename": "app1", "path.basenameNormalized": "app1"}, - {"path": "app2", "path.basename": "app2", "path.basenameNormalized": "app2"}, - {"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path.basenameNormalized": "app3"}, + {"path": "app1", "path.basename": "app1", "path[0]": "app1", "path.basenameNormalized": "app1"}, + {"path": "app2", "path.basename": "app2", "path[0]": "app2", "path.basenameNormalized": "app2"}, + {"path": "p2/app3", "path.basename": "app3", "path[0]": "p2", "path[1]": "app3", "path.basenameNormalized": "app3"}, }, expectedError: nil, }, @@ -238,7 +260,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) { "path": "cluster-config/production", "path.basename": "production", "path[0]": "cluster-config", + "path[1]": "production", "path.basenameNormalized": "production", + "path.filename": "config.json", + "path.filenameNormalized": "config.json", }, { "cluster.owner": "foo.bar@example.com", @@ -247,7 +272,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) { "path": "cluster-config/staging", "path.basename": "staging", "path[0]": "cluster-config", + "path[1]": "staging", "path.basenameNormalized": "staging", + "path.filename": "config.json", + "path.filenameNormalized": "config.json", }, }, expectedError: nil, @@ -305,7 +333,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) { "path": "cluster-config/production", "path.basename": "production", "path[0]": "cluster-config", + "path[1]": "production", "path.basenameNormalized": "production", + "path.filename": "config.json", + "path.filenameNormalized": "config.json", }, { "cluster.owner": "john.doe@example.com", @@ -314,7 +345,10 @@ func TestGitGenerateParamsFromFiles(t *testing.T) { "path": "cluster-config/production", "path.basename": "production", "path[0]": "cluster-config", + "path[1]": "production", "path.basenameNormalized": "production", + "path.filename": "config.json", + "path.filenameNormalized": "config.json", }, }, expectedError: nil, @@ -353,7 +387,10 @@ cluster: "path": "cluster-config/production", "path.basename": "production", "path[0]": "cluster-config", + "path[1]": "production", "path.basenameNormalized": "production", + "path.filename": "config.yaml", + "path.filenameNormalized": "config.yaml", }, { "cluster.owner": "foo.bar@example.com", @@ -362,7 +399,10 @@ cluster: "path": "cluster-config/staging", "path.basename": "staging", "path[0]": "cluster-config", + "path[1]": "staging", "path.basenameNormalized": "staging", + "path.filename": "config.yaml", + "path.filenameNormalized": "config.yaml", }, }, expectedError: nil, @@ -393,7 +433,10 @@ cluster: "path": "cluster-config/production", "path.basename": "production", "path[0]": "cluster-config", + "path[1]": "production", "path.basenameNormalized": "production", + "path.filename": "config.yaml", + "path.filenameNormalized": "config.yaml", }, { "cluster.owner": "john.doe@example.com", @@ -402,7 +445,10 @@ cluster: "path": "cluster-config/production", "path.basename": "production", "path[0]": "cluster-config", + "path[1]": "production", "path.basenameNormalized": "production", + "path.filename": "config.yaml", + "path.filenameNormalized": "config.yaml", }, }, expectedError: nil, diff --git a/docs/operator-manual/applicationset/Generators-Git.md b/docs/operator-manual/applicationset/Generators-Git.md index 944cdc969c0d0..78de8f51b9a17 100644 --- a/docs/operator-manual/applicationset/Generators-Git.md +++ b/docs/operator-manual/applicationset/Generators-Git.md @@ -65,15 +65,15 @@ The generator parameters are: - `{{path.basename}}`: For any directory path within the Git repository that matches the `path` wildcard, the right-most path name is extracted (e.g. `/directory/directory2` would produce `directory2`). - `{{path.basenameNormalized}}`: This field is the same as `path.basename` with unsupported characters replaced with `-` (e.g. a `path` of `/directory/directory_2`, and `path.basename` of `directory_2` would produce `directory-2` here). -**Note**: The right-most path name always becomes `{{path.basename}}`. For example, to use `four` as a parameter from `- path: /one/two/three/four`, use `{{path.basename}}` not `{{path[3]}}`. +**Note**: The right-most path name always becomes `{{path.basename}}`. For example, for `- path: /one/two/three/four`, `{{path.basename}}` is `four`. -Whenever a new Helm chart/Kustomize YAML/Application/plain subfolder is added to the Git repository, the ApplicationSet controller will detect this change and automatically deploy the resulting manifests within new `Application` resources. +Whenever a new Helm chart/Kustomize YAML/Application/plain subdirectory is added to the Git repository, the ApplicationSet controller will detect this change and automatically deploy the resulting manifests within new `Application` resources. As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them. ### Exclude directories -The Git directory generator will automatically exclude folders that begin with `.` (such as `.git`). +The Git directory generator will automatically exclude directories that begin with `.` (such as `.git`). The Git directory generator also supports an `exclude` option in order to exclude directories in the repository from being scanned by the ApplicationSet controller: @@ -207,7 +207,7 @@ Suppose you have a Git repository with the following directory structure: └── git-generator-files.yaml ``` -The folders are: +The directories are: - `guestbook` contains the Kubernetes resources for a simple guestbook application - `cluster-config` contains JSON/YAML files describing the individual engineering clusters: one for `dev` and one for `prod`. @@ -271,12 +271,15 @@ As with other generators, clusters *must* already be defined within Argo CD, in In addition to the flattened key/value pairs from the configuration file, the following generator parameters are provided: -- `{{path}}`: The path to the folder containing matching configuration file within the Git repository. Example: `/clusters/clusterA`, if the config file was `/clusters/clusterA/config.json` +- `{{path}}`: The path to the directory containing matching configuration file within the Git repository. Example: `/clusters/clusterA`, if the config file was `/clusters/clusterA/config.json` - `{{path[n]}}`: The path to the matching configuration file within the Git repository, split into array elements (`n` - array index). Example: `path[0]: clusters`, `path[1]: clusterA` -- `{{path.basename}}`: Basename of the path to the folder containing the configuration file (e.g. `clusterA`, with the above example.) +- `{{path.basename}}`: Basename of the path to the directory containing the configuration file (e.g. `clusterA`, with the above example.) - `{{path.basenameNormalized}}`: This field is the same as `path.basename` with unsupported characters replaced with `-` (e.g. a `path` of `/directory/directory_2`, and `path.basename` of `directory_2` would produce `directory-2` here). +- `{{path.filename}}`: The matched filename. e.g., `config.json` in the above example. +- `{{path.filenameNormalized}}`: The matched filename with unsupported characters replaced with `-`. -**Note**: The right-most path name always becomes `{{path.basename}}`. For example, to use `four` as a parameter from `- path: /one/two/three/four/config.json`, use `{{path.basename}}` not `{{path[3]}}`. +**Note**: The right-most *directory* name always becomes `{{path.basename}}`. For example, from `- path: /one/two/three/four/config.json`, `{{path.basename}}` will be `four`. +The filename can always be accessed using `{{path.filename}}`. ## Webhook Configuration