diff --git a/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md b/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md index d09f4f56bf..5513d36ec1 100644 --- a/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md +++ b/docs/content/en/docs-dev/operator-manual/piped/configuration-reference.md @@ -34,6 +34,7 @@ spec: | eventWatcher | [EventWatcher](/docs/operator-manual/piped/configuration-reference/#eventwatcher) | Optional Event watcher settings. | No | | secretManagement | [SecretManagement](/docs/operator-manual/piped/configuration-reference/#secretmanagement) | The using secret management method. | No | | notifications | [Notifications](/docs/operator-manual/piped/configuration-reference/#notifications) | Sending notifications to Slack, Webhook... | No | +| appSelector | map[string]string | List of labels to filter all applications this piped will handle. Currently, it is only be used to filter the applications suggested for adding from the control plane. | No | ## Git diff --git a/pkg/app/piped/appconfigreporter/appconfigreporter.go b/pkg/app/piped/appconfigreporter/appconfigreporter.go index c1be6d1d32..bb10ca7e57 100644 --- a/pkg/app/piped/appconfigreporter/appconfigreporter.go +++ b/pkg/app/piped/appconfigreporter/appconfigreporter.go @@ -307,7 +307,10 @@ func (r *Reporter) isSynced(appInfo *model.ApplicationInfo, app *model.Applicati // findUnregisteredApps finds out unregistered application info in the given git repository. // The file name must be default name in order to be recognized as an Application config. func (r *Reporter) findUnregisteredApps(repoPath, repoID string) ([]*model.ApplicationInfo, error) { - apps := r.applicationLister.List() + var ( + apps = r.applicationLister.List() + selector = r.config.AppSelector + ) // Create a map to determine the app is registered by GitPath. registeredAppPaths := make(map[string]struct{}, len(apps)) for _, app := range apps { @@ -355,6 +358,12 @@ func (r *Reporter) findUnregisteredApps(repoPath, repoID string) ([]*model.Appli // Continue reading so that it can return apps as much as possible. return nil } + + // Filter the apps by appSelector if appSelector set. + if len(selector) != 0 && !appInfo.ContainLabels(selector) { + return nil + } + out = append(out, appInfo) return nil }) diff --git a/pkg/app/piped/appconfigreporter/appconfigreporter_test.go b/pkg/app/piped/appconfigreporter/appconfigreporter_test.go index 40d2e9efd5..e1bd4989c1 100644 --- a/pkg/app/piped/appconfigreporter/appconfigreporter_test.go +++ b/pkg/app/piped/appconfigreporter/appconfigreporter_test.go @@ -181,6 +181,9 @@ func TestReporter_findUnregisteredApps(t *testing.T) { "path/to/repo-1/app-1/app.pipecd.yaml": &fstest.MapFile{Data: []byte("")}, }, logger: zap.NewNop(), + config: &config.PipedSpec{ + PipedID: "piped-1", + }, }, args: args{ repoPath: "invalid", @@ -198,6 +201,9 @@ func TestReporter_findUnregisteredApps(t *testing.T) { "path/to/repo-1/app-1/app.pipecd.yaml": &fstest.MapFile{Data: []byte("")}, }, logger: zap.NewNop(), + config: &config.PipedSpec{ + PipedID: "piped-1", + }, }, args: args{ repoPath: "path/to/repo-1", @@ -216,6 +222,9 @@ func TestReporter_findUnregisteredApps(t *testing.T) { fileSystem: fstest.MapFS{ "path/to/repo-1/app-1/app.pipecd.yaml": &fstest.MapFile{Data: []byte("invalid-text")}, }, + config: &config.PipedSpec{ + PipedID: "piped-1", + }, logger: zap.NewNop(), }, args: args{ @@ -229,7 +238,9 @@ func TestReporter_findUnregisteredApps(t *testing.T) { { name: "valid app config that is unregistered", reporter: &Reporter{ - config: &config.PipedSpec{PipedID: "piped-1"}, + config: &config.PipedSpec{ + PipedID: "piped-1", + }, applicationLister: &fakeApplicationLister{}, fileSystem: fstest.MapFS{ "path/to/repo-1/app-1/app.pipecd.yaml": &fstest.MapFile{Data: []byte(` @@ -262,7 +273,9 @@ spec: { name: "valid app config that name isn't default", reporter: &Reporter{ - config: &config.PipedSpec{PipedID: "piped-1"}, + config: &config.PipedSpec{ + PipedID: "piped-1", + }, applicationLister: &fakeApplicationLister{}, fileSystem: fstest.MapFS{ "path/to/repo-1/app-1/dev.pipecd.yaml": &fstest.MapFile{Data: []byte(` @@ -292,6 +305,80 @@ spec: }, wantErr: false, }, + { + name: "filtered by appSelector", + reporter: &Reporter{ + config: &config.PipedSpec{ + PipedID: "piped-1", + AppSelector: map[string]string{ + "env": "test", + }, + }, + applicationLister: &fakeApplicationLister{}, + fileSystem: fstest.MapFS{ + "path/to/repo-1/app-1/app.pipecd.yaml": &fstest.MapFile{Data: []byte(` +apiVersion: pipecd.dev/v1beta1 +kind: KubernetesApp +spec: + name: app-1 + labels: + key-1: value-1 + env: dev +`)}, + }, + logger: zap.NewNop(), + }, + args: args{ + repoPath: "path/to/repo-1", + repoID: "repo-1", + registeredAppPaths: map[string]string{}, + }, + want: []*model.ApplicationInfo{}, + wantErr: false, + }, + { + name: "match labels with appSelector", + reporter: &Reporter{ + config: &config.PipedSpec{ + PipedID: "piped-1", + AppSelector: map[string]string{ + "env": "test", + }, + }, + applicationLister: &fakeApplicationLister{}, + fileSystem: fstest.MapFS{ + "path/to/repo-1/app-1/dev.pipecd.yaml": &fstest.MapFile{Data: []byte(` +apiVersion: pipecd.dev/v1beta1 +kind: KubernetesApp +spec: + name: app-1 + labels: + key-1: value-1 + env: test +`)}, + }, + logger: zap.NewNop(), + }, + args: args{ + repoPath: "path/to/repo-1", + repoID: "repo-1", + registeredAppPaths: map[string]string{}, + }, + want: []*model.ApplicationInfo{ + { + Name: "app-1", + Labels: map[string]string{ + "key-1": "value-1", + "env": "test", + }, + RepoId: "repo-1", + Path: "app-1", + ConfigFilename: "dev.pipecd.yaml", + PipedId: "piped-1", + }, + }, + wantErr: false, + }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) {