From 87250688536f044cc1b45c228a5e8781b9a989f3 Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Sun, 15 Dec 2024 16:33:47 +1100 Subject: [PATCH] feat: collector --- cmd/collect_environment.go | 59 ++ cmd/collect_environment_test.go | 78 ++ cmd/root.go | 8 + cmd/validate_lagoonyml_test.go | 2 +- go.mod | 2 +- internal/collector/collector.go | 123 ++++ internal/collector/collector_test.go | 147 ++++ internal/collector/compose.go | 1 + internal/collector/cronjobs.go | 26 + internal/collector/cronjobs_test.go | 80 +++ internal/collector/dbaas_consumers.go | 60 ++ .../collector/dbaas_consumers_mariadb_test.go | 80 +++ .../collector/dbaas_consumers_mongodb_test.go | 80 +++ .../dbaas_consumers_postgres_test.go | 80 +++ internal/collector/deployments.go | 26 + internal/collector/deployments_test.go | 80 +++ internal/collector/ingress.go | 26 + internal/collector/ingress_test.go | 80 +++ internal/collector/lagoon.go | 1 + internal/collector/prebackuppods.go | 43 ++ internal/collector/prebackuppods_v1_test.go | 80 +++ .../collector/prebackuppods_v1alpha1_test.go | 80 +++ internal/collector/pvcs.go | 26 + internal/collector/pvcs_test.go | 80 +++ internal/collector/schedules .go | 43 ++ internal/collector/schedules_v1_test.go | 80 +++ internal/collector/schedules_v1alpha1_test.go | 80 +++ internal/collector/secrets.go | 26 + internal/collector/secrets_test.go | 80 +++ internal/collector/services.go | 26 + internal/collector/services_test.go | 80 +++ .../testdata/json-result/result-1.json | 680 ++++++++++++++++++ .../testdata/json-result/result-2.json | 440 ++++++++++++ .../result/result-1/lagoon-cronjobs.yaml | 93 +++ .../result/result-1/lagoon-deployments.yaml | 96 +++ .../result/result-1/lagoon-ingress.yaml | 103 +++ .../result-1/lagoon-mariadb-consumers.yaml | 2 + .../result-1/lagoon-mongodb-consumers.yaml | 2 + .../result-1/lagoon-postgres-consumers.yaml | 2 + .../result-1/lagoon-prebackuppods-v1.yaml | 2 + .../lagoon-prebackuppods-v1alpha1.yaml | 60 ++ .../testdata/result/result-1/lagoon-pvcs.yaml | 2 + .../result/result-1/lagoon-schedules-v1.yaml | 2 + .../result-1/lagoon-schedules-v1alpha1.yaml | 44 ++ .../result/result-1/lagoon-secrets.yaml | 2 + .../result/result-1/lagoon-services.yaml | 42 ++ .../result/result-2/lagoon-cronjobs.yaml | 2 + .../result/result-2/lagoon-deployments.yaml | 103 +++ .../result/result-2/lagoon-ingress.yaml | 103 +++ .../result-2/lagoon-mariadb-consumers.yaml | 2 + .../result-2/lagoon-mongodb-consumers.yaml | 2 + .../result-2/lagoon-postgres-consumers.yaml | 2 + .../result-2/lagoon-prebackuppods-v1.yaml | 2 + .../lagoon-prebackuppods-v1alpha1.yaml | 2 + .../result/result-2/lagoon-schedules-v1.yaml | 2 + .../result-2/lagoon-schedules-v1alpha1.yaml | 2 + .../result/result-2/lagoon-secrets.yaml | 2 + .../result/result-2/lagoon-services.yaml | 34 + .../result/result-empty/lagoon-cronjobs.yaml | 2 + .../result-empty/lagoon-deployments.yaml | 2 + .../result/result-empty/lagoon-ingress.yaml | 2 + .../lagoon-mariadb-consumers.yaml | 2 + .../lagoon-mongodb-consumers.yaml | 2 + .../lagoon-postgres-consumers.yaml | 2 + .../result-empty/lagoon-prebackuppods-v1.yaml | 2 + .../lagoon-prebackuppods-v1alpha1.yaml | 2 + .../result/result-empty/lagoon-pvcs.yaml | 2 + .../result-empty/lagoon-schedules-v1.yaml | 2 + .../lagoon-schedules-v1alpha1.yaml | 2 + .../result/result-empty/lagoon-secrets.yaml | 2 + .../result/result-empty/lagoon-services.yaml | 2 + .../seed/seed-1/cronjob-cronjob-node-env.yaml | 90 +++ .../testdata/seed/seed-1/deployment-node.yaml | 93 +++ .../seed/seed-1/ingress-example.com.yaml | 52 ++ .../testdata/seed/seed-1/ingress-node.yaml | 47 ++ .../seed-1/k8up-lagoon-backup-schedule.yaml | 41 ++ .../seed/seed-1/prebackuppod-mariadb.yaml | 56 ++ .../testdata/seed/seed-1/service-node.yaml | 39 + .../testdata/seed/seed-2/deployment-node.yaml | 100 +++ .../seed/seed-2/ingress-example.com.yaml | 52 ++ .../testdata/seed/seed-2/ingress-node.yaml | 47 ++ .../seed/seed-2/pvc-custom-config.yaml | 29 + .../seed/seed-2/pvc-custom-files.yaml | 29 + .../testdata/seed/seed-2/pvc-node.yaml | 30 + .../testdata/seed/seed-2/service-node.yaml | 31 + .../testdata/seed/seed-empty/.gitkeep | 0 internal/k8s/client.go | 117 +++ legacy/build-deploy-docker-compose.sh | 45 ++ 88 files changed, 4515 insertions(+), 2 deletions(-) create mode 100644 cmd/collect_environment.go create mode 100644 cmd/collect_environment_test.go create mode 100644 internal/collector/collector.go create mode 100644 internal/collector/collector_test.go create mode 100644 internal/collector/compose.go create mode 100644 internal/collector/cronjobs.go create mode 100644 internal/collector/cronjobs_test.go create mode 100644 internal/collector/dbaas_consumers.go create mode 100644 internal/collector/dbaas_consumers_mariadb_test.go create mode 100644 internal/collector/dbaas_consumers_mongodb_test.go create mode 100644 internal/collector/dbaas_consumers_postgres_test.go create mode 100644 internal/collector/deployments.go create mode 100644 internal/collector/deployments_test.go create mode 100644 internal/collector/ingress.go create mode 100644 internal/collector/ingress_test.go create mode 100644 internal/collector/lagoon.go create mode 100644 internal/collector/prebackuppods.go create mode 100644 internal/collector/prebackuppods_v1_test.go create mode 100644 internal/collector/prebackuppods_v1alpha1_test.go create mode 100644 internal/collector/pvcs.go create mode 100644 internal/collector/pvcs_test.go create mode 100644 internal/collector/schedules .go create mode 100644 internal/collector/schedules_v1_test.go create mode 100644 internal/collector/schedules_v1alpha1_test.go create mode 100644 internal/collector/secrets.go create mode 100644 internal/collector/secrets_test.go create mode 100644 internal/collector/services.go create mode 100644 internal/collector/services_test.go create mode 100644 internal/collector/testdata/json-result/result-1.json create mode 100644 internal/collector/testdata/json-result/result-2.json create mode 100644 internal/collector/testdata/result/result-1/lagoon-cronjobs.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-deployments.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-ingress.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-mariadb-consumers.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-mongodb-consumers.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-postgres-consumers.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1alpha1.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-pvcs.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-schedules-v1.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-schedules-v1alpha1.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-secrets.yaml create mode 100644 internal/collector/testdata/result/result-1/lagoon-services.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-cronjobs.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-deployments.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-ingress.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-mariadb-consumers.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-mongodb-consumers.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-postgres-consumers.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1alpha1.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-schedules-v1.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-schedules-v1alpha1.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-secrets.yaml create mode 100644 internal/collector/testdata/result/result-2/lagoon-services.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-cronjobs.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-deployments.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-ingress.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-mariadb-consumers.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-mongodb-consumers.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-postgres-consumers.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1alpha1.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-pvcs.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-schedules-v1.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-schedules-v1alpha1.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-secrets.yaml create mode 100644 internal/collector/testdata/result/result-empty/lagoon-services.yaml create mode 100644 internal/collector/testdata/seed/seed-1/cronjob-cronjob-node-env.yaml create mode 100644 internal/collector/testdata/seed/seed-1/deployment-node.yaml create mode 100644 internal/collector/testdata/seed/seed-1/ingress-example.com.yaml create mode 100644 internal/collector/testdata/seed/seed-1/ingress-node.yaml create mode 100644 internal/collector/testdata/seed/seed-1/k8up-lagoon-backup-schedule.yaml create mode 100644 internal/collector/testdata/seed/seed-1/prebackuppod-mariadb.yaml create mode 100644 internal/collector/testdata/seed/seed-1/service-node.yaml create mode 100644 internal/collector/testdata/seed/seed-2/deployment-node.yaml create mode 100644 internal/collector/testdata/seed/seed-2/ingress-example.com.yaml create mode 100644 internal/collector/testdata/seed/seed-2/ingress-node.yaml create mode 100644 internal/collector/testdata/seed/seed-2/pvc-custom-config.yaml create mode 100644 internal/collector/testdata/seed/seed-2/pvc-custom-files.yaml create mode 100644 internal/collector/testdata/seed/seed-2/pvc-node.yaml create mode 100644 internal/collector/testdata/seed/seed-2/service-node.yaml create mode 100644 internal/collector/testdata/seed/seed-empty/.gitkeep create mode 100644 internal/k8s/client.go diff --git a/cmd/collect_environment.go b/cmd/collect_environment.go new file mode 100644 index 00000000..7f757970 --- /dev/null +++ b/cmd/collect_environment.go @@ -0,0 +1,59 @@ +package cmd + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/spf13/cobra" + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/helpers" + "github.com/uselagoon/build-deploy-tool/internal/k8s" +) + +func init() { + collectCmd.AddCommand(collectEnvironment) +} + +var collectEnvironment = &cobra.Command{ + Use: "environment", + Aliases: []string{"e"}, + Short: "Collect seed information about the environment", + RunE: func(cmd *cobra.Command, args []string) error { + // get a k8s client + client, err := k8s.NewClient() + if err != nil { + return err + } + // create a collector + col := collector.NewCollector(client) + namespace := helpers.GetEnv("NAMESPACE", "", false) + namespace, err = helpers.GetNamespace(namespace, "/var/run/secrets/kubernetes.io/serviceaccount/namespace") + if err != nil { + return err + } + if namespace == "" { + return fmt.Errorf("unable to detect namespace") + } + // collect the environment + data, err := CollectEnvironment(col, namespace) + if err != nil { + return err + } + env, err := json.MarshalIndent(data, "", " ") + if err != nil { + return err + } + fmt.Println(string(env)) + return nil + }, +} + +// CollectEnvironment . +func CollectEnvironment(c *collector.Collector, namespace string) (*collector.LagoonEnvState, error) { + state, err := c.Collect(context.Background(), namespace) + if err != nil { + return nil, err + } + return state, nil +} diff --git a/cmd/collect_environment_test.go b/cmd/collect_environment_test.go new file mode 100644 index 00000000..2547b473 --- /dev/null +++ b/cmd/collect_environment_test.go @@ -0,0 +1,78 @@ +package cmd + +import ( + "encoding/json" + "os" + "reflect" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + + // changes the testing to source from root so paths to test resources must be defined from repo root + _ "github.com/uselagoon/build-deploy-tool/internal/testing" +) + +func TestCollectEnvironment(t *testing.T) { + type args struct { + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + + { + name: "list-environment", + args: args{ + namespace: "example-project-main", + }, + seedDir: "internal/collector/testdata/seed/seed-1", + want: "internal/collector/testdata/json-result/result-1.json", + wantErr: false, + }, + + { + name: "list-environment-with-pvcs", + args: args{ + namespace: "example-project-main", + }, + seedDir: "internal/collector/testdata/seed/seed-2", + want: "internal/collector/testdata/json-result/result-2.json", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + col := collector.NewCollector(client) + got, err := CollectEnvironment(col, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("CollectEnvironment() error = %v, wantErr %v", err, tt.wantErr) + return + } + results, err := os.ReadFile(tt.want) + if err != nil { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + env, err := json.MarshalIndent(got, "", " ") + if err != nil { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + if !reflect.DeepEqual(string(results), string(env)) { + t.Errorf("Collect() = \n%v", diff.LineDiff(string(env), string(results))) + } + }) + } +} diff --git a/cmd/root.go b/cmd/root.go index e88ae3cc..62c4866a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -60,6 +60,13 @@ var validateCmd = &cobra.Command{ Long: `Validate resources for Lagoon builds`, } +var collectCmd = &cobra.Command{ + Use: "collect", + Aliases: []string{"col", "c"}, + Short: "Collect resource information", + Long: `Collect resource information for Lagoon builds`, +} + // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { @@ -99,6 +106,7 @@ func init() { rootCmd.AddCommand(taskCmd) rootCmd.AddCommand(identifyCmd) rootCmd.AddCommand(validateCmd) + rootCmd.AddCommand(collectCmd) rootCmd.PersistentFlags().StringP("lagoon-yml", "l", ".lagoon.yml", "The .lagoon.yml file to read") diff --git a/cmd/validate_lagoonyml_test.go b/cmd/validate_lagoonyml_test.go index 0372345f..c7f3e319 100644 --- a/cmd/validate_lagoonyml_test.go +++ b/cmd/validate_lagoonyml_test.go @@ -171,7 +171,7 @@ func TestValidateLagoonYml(t *testing.T) { err = yaml.Unmarshal(wantsLYAMLString, wantsLYAML) if err != nil { - t.Errorf(err.Error()) + t.Errorf("couldn't unmarshal yaml: %v", err) return } diff --git a/go.mod b/go.mod index 4587f3a5..8010c565 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( k8s.io/api v0.32.1 k8s.io/apimachinery v0.32.1 k8s.io/client-go v0.32.1 + sigs.k8s.io/controller-runtime v0.20.0 sigs.k8s.io/yaml v1.4.0 ) @@ -83,7 +84,6 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect - sigs.k8s.io/controller-runtime v0.20.0 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect ) diff --git a/internal/collector/collector.go b/internal/collector/collector.go new file mode 100644 index 00000000..415489bc --- /dev/null +++ b/internal/collector/collector.go @@ -0,0 +1,123 @@ +package collector + +import ( + "context" + "strings" + + k8upv1 "github.com/k8up-io/k8up/v2/api/v1" + k8upv1alpha1 "github.com/vshn/k8up/api/v1alpha1" + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + networkv1 "k8s.io/api/networking/v1" + + mariadbv1 "github.com/amazeeio/dbaas-operator/apis/mariadb/v1" + mongodbv1 "github.com/amazeeio/dbaas-operator/apis/mongodb/v1" + postgresv1 "github.com/amazeeio/dbaas-operator/apis/postgres/v1" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +type Collector struct { + Client client.Client +} + +type LagoonEnvState struct { + Deployments *appsv1.DeploymentList `json:"deployments"` + Cronjobs *batchv1.CronJobList `json:"cronjobs"` + Ingress *networkv1.IngressList `json:"ingress"` + Services *corev1.ServiceList `json:"services"` + Secrets *corev1.SecretList `json:"secrets"` + PVCs *corev1.PersistentVolumeClaimList `json:"pvcs"` + SchedulesV1 *k8upv1.ScheduleList `json:"schedulesv1"` + SchedulesV1Alpha1 *k8upv1alpha1.ScheduleList `json:"schedulesv1alpha1"` + PreBackupPodsV1 *k8upv1.PreBackupPodList `json:"prebackuppodsv1"` + PreBackupPodsV1Alpha1 *k8upv1alpha1.PreBackupPodList `json:"prebackuppodsv1alpha1"` + MariaDBConsumers *mariadbv1.MariaDBConsumerList `json:"mariadbconsumers"` + MongoDBConsumers *mongodbv1.MongoDBConsumerList `json:"mongodbconsumers"` + PostgreSQLConsumers *postgresv1.PostgreSQLConsumerList `json:"postgresqlconsumers"` +} + +func NewCollector(client client.Client) *Collector { + return &Collector{ + Client: client, + } +} + +func (c *Collector) Collect(ctx context.Context, namespace string) (*LagoonEnvState, error) { + var state LagoonEnvState + var err error + state.Deployments, err = c.CollectDeployments(ctx, namespace) + if err != nil { + return nil, err + } + state.Cronjobs, err = c.CollectCronjobs(ctx, namespace) + if err != nil { + return nil, err + } + state.Ingress, err = c.CollectIngress(ctx, namespace) + if err != nil { + return nil, err + } + state.Services, err = c.CollectServices(ctx, namespace) + if err != nil { + return nil, err + } + state.Secrets, err = c.CollectSecrets(ctx, namespace) + if err != nil { + return nil, err + } + state.PVCs, err = c.CollectPVCs(ctx, namespace) + if err != nil { + return nil, err + } + state.MariaDBConsumers, err = c.CollectMariaDBConsumers(ctx, namespace) + if err != nil { + // handle if consumer crds not installed + if !strings.Contains(err.Error(), "no kind is registered for the type") { + return nil, err + } + } + state.MongoDBConsumers, err = c.CollectMongoDBConsumers(ctx, namespace) + if err != nil { + // handle if consumer crds not installed + if !strings.Contains(err.Error(), "no kind is registered for the type") { + return nil, err + } + } + state.PostgreSQLConsumers, err = c.CollectPostgreSQLConsumers(ctx, namespace) + if err != nil { + // handle if consumer crds not installed + if !strings.Contains(err.Error(), "no kind is registered for the type") { + return nil, err + } + } + state.SchedulesV1, err = c.CollectSchedulesV1(ctx, namespace) + if err != nil { + // handle if k8up v1 crds not installed + if !strings.Contains(err.Error(), "no kind is registered for the type") { + return nil, err + } + } + state.SchedulesV1Alpha1, err = c.CollectSchedulesV1Alpha1(ctx, namespace) + if err != nil { + // handle if k8up v1alpha1 crds not installed + if !strings.Contains(err.Error(), "no kind is registered for the type") { + return nil, err + } + } + state.PreBackupPodsV1, err = c.CollectPreBackupPodsV1(ctx, namespace) + if err != nil { + // handle if k8up v1 crds not installed + if !strings.Contains(err.Error(), "no kind is registered for the type") { + return nil, err + } + } + state.PreBackupPodsV1Alpha1, err = c.CollectPreBackupPodsV1Alpha1(ctx, namespace) + if err != nil { + // handle if k8up v1alpha1 crds not installed + if !strings.Contains(err.Error(), "no kind is registered for the type") { + return nil, err + } + } + return &state, nil +} diff --git a/internal/collector/collector_test.go b/internal/collector/collector_test.go new file mode 100644 index 00000000..db6f9b5e --- /dev/null +++ b/internal/collector/collector_test.go @@ -0,0 +1,147 @@ +package collector + +import ( + "context" + "fmt" + "os" + "reflect" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_Collect(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + // want *LagoonEnvState + seedDir string + want string + wantErr bool + }{ + { + name: "list-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/", + wantErr: false, + }, + { + name: "list-environment-pvc", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-2", + want: "testdata/result/result-2/", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.Collect(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.Collect() error = %v, wantErr %v", err, tt.wantErr) + return + } + results, err := os.ReadDir(tt.want) + if err != nil { + t.Errorf("couldn't read directory %v: %v", tt.want, err) + } + for _, r := range results { + var rBytes []byte + switch r.Name() { + case "lagoon-deployments.yaml": + rBytes, err = yaml.Marshal(got.Deployments) + if err != nil { + t.Errorf("couldn't marshal deployments: %v", err) + } + case "lagoon-cronjobs.yaml": + rBytes, err = yaml.Marshal(got.Cronjobs) + if err != nil { + t.Errorf("couldn't marshal cronjobs: %v", err) + } + case "lagoon-ingress.yaml": + rBytes, err = yaml.Marshal(got.Ingress) + if err != nil { + t.Errorf("couldn't marshal ingress: %v", err) + } + case "lagoon-services.yaml": + rBytes, err = yaml.Marshal(got.Services) + if err != nil { + t.Errorf("couldn't marshal services: %v", err) + } + case "lagoon-secrets.yaml": + rBytes, err = yaml.Marshal(got.Secrets) + if err != nil { + t.Errorf("couldn't marshal secrets: %v", err) + } + case "lagoon-mariadb-consumers.yaml": + rBytes, err = yaml.Marshal(got.MariaDBConsumers) + if err != nil { + t.Errorf("couldn't marshal mariadb-consumers: %v", err) + } + case "lagoon-mongodb-consumers.yaml": + rBytes, err = yaml.Marshal(got.MongoDBConsumers) + if err != nil { + t.Errorf("couldn't marshal mongodb-consumers: %v", err) + } + case "lagoon-postgres-consumers.yaml": + rBytes, err = yaml.Marshal(got.PostgreSQLConsumers) + if err != nil { + t.Errorf("couldn't marshal postgres-consumers: %v", err) + } + case "lagoon-schedules-v1.yaml": + rBytes, err = yaml.Marshal(got.SchedulesV1) + if err != nil { + t.Errorf("couldn't marshal schedules-v1: %v", err) + } + case "lagoon-schedules-v1alpha1.yaml": + rBytes, err = yaml.Marshal(got.SchedulesV1Alpha1) + if err != nil { + t.Errorf("couldn't marshal schedules-v1alpha1: %v", err) + } + case "lagoon-prebackuppods-v1.yaml": + rBytes, err = yaml.Marshal(got.PreBackupPodsV1) + if err != nil { + t.Errorf("couldn't marshal prebackuppods-v1: %v", err) + } + case "lagoon-prebackuppods-v1alpha1.yaml": + rBytes, err = yaml.Marshal(got.PreBackupPodsV1Alpha1) + if err != nil { + t.Errorf("couldn't marshal prebackuppods-v1alpha1: %v", err) + } + default: + continue + } + r1, err := os.ReadFile(fmt.Sprintf("%s/%s", tt.want, r.Name())) + if err != nil { + t.Errorf("couldn't read file %v: %v", fmt.Sprintf("%s/%s", tt.want, r.Name()), err) + } + if !reflect.DeepEqual(rBytes, r1) { + t.Errorf("Collect() = \n%v", diff.LineDiff(string(r1), string(rBytes))) + } + } + }) + } +} diff --git a/internal/collector/compose.go b/internal/collector/compose.go new file mode 100644 index 00000000..66f94de8 --- /dev/null +++ b/internal/collector/compose.go @@ -0,0 +1 @@ +package collector diff --git a/internal/collector/cronjobs.go b/internal/collector/cronjobs.go new file mode 100644 index 00000000..dd83aa46 --- /dev/null +++ b/internal/collector/cronjobs.go @@ -0,0 +1,26 @@ +package collector + +import ( + "context" + + batchv1 "k8s.io/api/batch/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectCronjobs(ctx context.Context, namespace string) (*batchv1.CronJobList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &batchv1.CronJobList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/cronjobs_test.go b/internal/collector/cronjobs_test.go new file mode 100644 index 00000000..e40021f1 --- /dev/null +++ b/internal/collector/cronjobs_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectCronjobs(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-cronjobs.yaml", + wantErr: false, + }, + { + name: "list-cronjobs", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-cronjobs.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectCronjobs(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectCronjobs() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectCronjobs() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/dbaas_consumers.go b/internal/collector/dbaas_consumers.go new file mode 100644 index 00000000..e1afc0ed --- /dev/null +++ b/internal/collector/dbaas_consumers.go @@ -0,0 +1,60 @@ +package collector + +import ( + "context" + + mariadbv1 "github.com/amazeeio/dbaas-operator/apis/mariadb/v1" + mongodbv1 "github.com/amazeeio/dbaas-operator/apis/mongodb/v1" + postgresv1 "github.com/amazeeio/dbaas-operator/apis/postgres/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectMariaDBConsumers(ctx context.Context, namespace string) (*mariadbv1.MariaDBConsumerList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &mariadbv1.MariaDBConsumerList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} + +func (c *Collector) CollectMongoDBConsumers(ctx context.Context, namespace string) (*mongodbv1.MongoDBConsumerList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &mongodbv1.MongoDBConsumerList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} + +func (c *Collector) CollectPostgreSQLConsumers(ctx context.Context, namespace string) (*postgresv1.PostgreSQLConsumerList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &postgresv1.PostgreSQLConsumerList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/dbaas_consumers_mariadb_test.go b/internal/collector/dbaas_consumers_mariadb_test.go new file mode 100644 index 00000000..b6c29f3e --- /dev/null +++ b/internal/collector/dbaas_consumers_mariadb_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectMariaDBConsumers(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-mariadb-consumers.yaml", + wantErr: false, + }, + { + name: "list-mariadb-consumers", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-mariadb-consumers.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectMariaDBConsumers(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectMariaDBConsumers() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectMariaDBConsumers() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/dbaas_consumers_mongodb_test.go b/internal/collector/dbaas_consumers_mongodb_test.go new file mode 100644 index 00000000..10d9c0dc --- /dev/null +++ b/internal/collector/dbaas_consumers_mongodb_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectMongoDBConsumers(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-mongodb-consumers.yaml", + wantErr: false, + }, + { + name: "list-mongodb-consumers", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-mongodb-consumers.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectMongoDBConsumers(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectMongoDBConsumers() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectMongoDBConsumers() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/dbaas_consumers_postgres_test.go b/internal/collector/dbaas_consumers_postgres_test.go new file mode 100644 index 00000000..8db7b7df --- /dev/null +++ b/internal/collector/dbaas_consumers_postgres_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectPostgreSQLConsumers(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-postgres-consumers.yaml", + wantErr: false, + }, + { + name: "list-postgres-consumers", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-postgres-consumers.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectPostgreSQLConsumers(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectPostgreSQLConsumers() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectPostgreSQLConsumers() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/deployments.go b/internal/collector/deployments.go new file mode 100644 index 00000000..7d603135 --- /dev/null +++ b/internal/collector/deployments.go @@ -0,0 +1,26 @@ +package collector + +import ( + "context" + + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectDeployments(ctx context.Context, namespace string) (*appsv1.DeploymentList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &appsv1.DeploymentList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/deployments_test.go b/internal/collector/deployments_test.go new file mode 100644 index 00000000..f49024cc --- /dev/null +++ b/internal/collector/deployments_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectDeployments(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-deployments.yaml", + wantErr: false, + }, + { + name: "list-deployments", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-deployments.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectDeployments(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectDeployments() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectDeployments() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/ingress.go b/internal/collector/ingress.go new file mode 100644 index 00000000..31c029c8 --- /dev/null +++ b/internal/collector/ingress.go @@ -0,0 +1,26 @@ +package collector + +import ( + "context" + + networkv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectIngress(ctx context.Context, namespace string) (*networkv1.IngressList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &networkv1.IngressList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/ingress_test.go b/internal/collector/ingress_test.go new file mode 100644 index 00000000..0f20b961 --- /dev/null +++ b/internal/collector/ingress_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectIngress(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-ingress.yaml", + wantErr: false, + }, + { + name: "list-services", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-ingress.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectIngress(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectIngress() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectIngress() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/lagoon.go b/internal/collector/lagoon.go new file mode 100644 index 00000000..66f94de8 --- /dev/null +++ b/internal/collector/lagoon.go @@ -0,0 +1 @@ +package collector diff --git a/internal/collector/prebackuppods.go b/internal/collector/prebackuppods.go new file mode 100644 index 00000000..4424a7c9 --- /dev/null +++ b/internal/collector/prebackuppods.go @@ -0,0 +1,43 @@ +package collector + +import ( + "context" + + k8upv1 "github.com/k8up-io/k8up/v2/api/v1" + k8upv1alpha1 "github.com/vshn/k8up/api/v1alpha1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectPreBackupPodsV1(ctx context.Context, namespace string) (*k8upv1.PreBackupPodList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &k8upv1.PreBackupPodList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} + +func (c *Collector) CollectPreBackupPodsV1Alpha1(ctx context.Context, namespace string) (*k8upv1alpha1.PreBackupPodList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &k8upv1alpha1.PreBackupPodList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/prebackuppods_v1_test.go b/internal/collector/prebackuppods_v1_test.go new file mode 100644 index 00000000..6b2ceb1f --- /dev/null +++ b/internal/collector/prebackuppods_v1_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectPreBackupPodsV1(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-prebackuppods-v1.yaml", + wantErr: false, + }, + { + name: "list-prebackuppods", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-prebackuppods-v1.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectPreBackupPodsV1(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectPreBackupPodsV1() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectPreBackupPodsV1() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/prebackuppods_v1alpha1_test.go b/internal/collector/prebackuppods_v1alpha1_test.go new file mode 100644 index 00000000..84e87dd2 --- /dev/null +++ b/internal/collector/prebackuppods_v1alpha1_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectPreBackupPodsV1Alpha1(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-prebackuppods-v1alpha1.yaml", + wantErr: false, + }, + { + name: "list-prebackuppods", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-prebackuppods-v1alpha1.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectPreBackupPodsV1Alpha1(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectPreBackupPodsV1Alpha1() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectPreBackupPodsV1Alpha1() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/pvcs.go b/internal/collector/pvcs.go new file mode 100644 index 00000000..65859abf --- /dev/null +++ b/internal/collector/pvcs.go @@ -0,0 +1,26 @@ +package collector + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectPVCs(ctx context.Context, namespace string) (*corev1.PersistentVolumeClaimList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &corev1.PersistentVolumeClaimList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/pvcs_test.go b/internal/collector/pvcs_test.go new file mode 100644 index 00000000..be85719a --- /dev/null +++ b/internal/collector/pvcs_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectPVCs(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-pvcs.yaml", + wantErr: false, + }, + { + name: "list-secrets", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-pvcs.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectPVCs(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectPVCs() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectPVCs() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/schedules .go b/internal/collector/schedules .go new file mode 100644 index 00000000..2d779ab9 --- /dev/null +++ b/internal/collector/schedules .go @@ -0,0 +1,43 @@ +package collector + +import ( + "context" + + k8upv1 "github.com/k8up-io/k8up/v2/api/v1" + k8upv1alpha1 "github.com/vshn/k8up/api/v1alpha1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectSchedulesV1(ctx context.Context, namespace string) (*k8upv1.ScheduleList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &k8upv1.ScheduleList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} + +func (c *Collector) CollectSchedulesV1Alpha1(ctx context.Context, namespace string) (*k8upv1alpha1.ScheduleList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &k8upv1alpha1.ScheduleList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/schedules_v1_test.go b/internal/collector/schedules_v1_test.go new file mode 100644 index 00000000..2ceb1bc4 --- /dev/null +++ b/internal/collector/schedules_v1_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectSchedulesV1(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-schedules-v1.yaml", + wantErr: false, + }, + { + name: "list-schedules", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-schedules-v1.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectSchedulesV1(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectSchedulesV1() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectSchedulesV1() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/schedules_v1alpha1_test.go b/internal/collector/schedules_v1alpha1_test.go new file mode 100644 index 00000000..a8377aa9 --- /dev/null +++ b/internal/collector/schedules_v1alpha1_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectSchedulesV1Alpha1(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-schedules-v1alpha1.yaml", + wantErr: false, + }, + { + name: "list-schedules", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-schedules-v1alpha1.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectSchedulesV1Alpha1(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectSchedulesV1Alpha1() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectSchedulesV1Alpha1() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/secrets.go b/internal/collector/secrets.go new file mode 100644 index 00000000..10aa74be --- /dev/null +++ b/internal/collector/secrets.go @@ -0,0 +1,26 @@ +package collector + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectSecrets(ctx context.Context, namespace string) (*corev1.SecretList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &corev1.SecretList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/secrets_test.go b/internal/collector/secrets_test.go new file mode 100644 index 00000000..e0cbbfd5 --- /dev/null +++ b/internal/collector/secrets_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectSecrets(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-secrets.yaml", + wantErr: false, + }, + { + name: "list-secrets", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-secrets.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectSecrets(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectSecrets() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectSecrets() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/services.go b/internal/collector/services.go new file mode 100644 index 00000000..0d6014bc --- /dev/null +++ b/internal/collector/services.go @@ -0,0 +1,26 @@ +package collector + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func (c *Collector) CollectServices(ctx context.Context, namespace string) (*corev1.ServiceList, error) { + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ + client.InNamespace(namespace), + client.MatchingLabelsSelector{ + Selector: labels.NewSelector().Add(*labelRequirements1), + }, + }) + list := &corev1.ServiceList{} + err := c.Client.List(ctx, list, listOption) + if err != nil { + return nil, err + } + return list, nil +} diff --git a/internal/collector/services_test.go b/internal/collector/services_test.go new file mode 100644 index 00000000..cb8eb325 --- /dev/null +++ b/internal/collector/services_test.go @@ -0,0 +1,80 @@ +package collector + +import ( + "context" + "os" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "sigs.k8s.io/yaml" +) + +func TestCollector_CollectServices(t *testing.T) { + type args struct { + ctx context.Context + namespace string + } + tests := []struct { + name string + args args + seedDir string + want string + wantErr bool + }{ + { + name: "new-environment", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-empty", + want: "testdata/result/result-empty/lagoon-services.yaml", + wantErr: false, + }, + { + name: "list-services", + args: args{ + ctx: context.Background(), + namespace: "example-project-main", + }, + seedDir: "testdata/seed/seed-1", + want: "testdata/result/result-1/lagoon-services.yaml", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := k8s.NewFakeClient(tt.args.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.args.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + c := &Collector{ + Client: client, + } + got, err := c.CollectServices(tt.args.ctx, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("Collector.CollectServices() error = %v, wantErr %v", err, tt.wantErr) + return + } + oJ, _ := yaml.Marshal(got) + results, err := os.ReadFile(tt.want) + if err != nil { + // try create the file if it doesn't exist + err := os.WriteFile(tt.want, oJ, 0644) + if err != nil { + t.Errorf("couldn't write file %v: %v", tt.want, err) + } else { + t.Errorf("couldn't read file %v: %v", tt.want, err) + } + } + if string(oJ) != string(results) { + t.Errorf("Collector.CollectServices() = \n%v", diff.LineDiff(string(results), string(oJ))) + } + }) + } +} diff --git a/internal/collector/testdata/json-result/result-1.json b/internal/collector/testdata/json-result/result-1.json new file mode 100644 index 00000000..ce5dbb9e --- /dev/null +++ b/internal/collector/testdata/json-result/result-1.json @@ -0,0 +1,680 @@ +{ + "deployments": { + "metadata": {}, + "items": [ + { + "kind": "Deployment", + "apiVersion": "apps/v1", + "metadata": { + "name": "node", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "basic", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic", + "lagoon.sh/template": "basic-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "replicas": 1, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/name": "basic" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "basic", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic", + "lagoon.sh/template": "basic-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/configMapSha": "abcdefg1234567890", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "containers": [ + { + "name": "basic", + "image": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "ports": [ + { + "name": "tcp-1234", + "containerPort": 1234, + "protocol": "TCP" + }, + { + "name": "tcp-8191", + "containerPort": 8191, + "protocol": "TCP" + }, + { + "name": "udp-9001", + "containerPort": 9001, + "protocol": "UDP" + } + ], + "envFrom": [ + { + "configMapRef": { + "name": "lagoon-env" + } + } + ], + "env": [ + { + "name": "LAGOON_GIT_SHA", + "value": "abcdefg123456" + }, + { + "name": "CRONJOBS" + }, + { + "name": "SERVICE_NAME", + "value": "node" + } + ], + "resources": { + "requests": { + "cpu": "10m", + "memory": "10Mi" + } + }, + "livenessProbe": { + "tcpSocket": { + "port": 1234 + }, + "initialDelaySeconds": 60, + "timeoutSeconds": 10 + }, + "readinessProbe": { + "tcpSocket": { + "port": 1234 + }, + "initialDelaySeconds": 1, + "timeoutSeconds": 1 + }, + "imagePullPolicy": "Always", + "securityContext": {} + } + ], + "imagePullSecrets": [ + { + "name": "lagoon-internal-registry-secret" + }, + { + "name": "lagoon-private-registry-dockerhub" + }, + { + "name": "lagoon-private-registry-my-custom-registry" + }, + { + "name": "lagoon-private-registry-my-hardcode-registry" + }, + { + "name": "lagoon-private-registry-my-other-registry" + } + ], + "priorityClassName": "lagoon-priority-production", + "enableServiceLinks": false + } + }, + "strategy": {} + }, + "status": {} + } + ] + }, + "cronjobs": { + "metadata": {}, + "items": [ + { + "kind": "CronJob", + "apiVersion": "batch/v1", + "metadata": { + "name": "cronjob-node-env", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "cronjob-node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "cronjob-basic", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic", + "lagoon.sh/template": "basic-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "schedule": "18,48 * * * *", + "startingDeadlineSeconds": 240, + "concurrencyPolicy": "Forbid", + "jobTemplate": { + "metadata": { + "creationTimestamp": null + }, + "spec": { + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "cronjob-node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "cronjob-basic", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic", + "lagoon.sh/template": "basic-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/configMapSha": "abcdefg1234567890", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "volumes": [ + { + "name": "lagoon-sshkey", + "secret": { + "secretName": "lagoon-sshkey", + "defaultMode": 420 + } + } + ], + "containers": [ + { + "name": "cronjob-node-env", + "image": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "command": [ + "/lagoon/cronjob.sh", + "env" + ], + "envFrom": [ + { + "configMapRef": { + "name": "lagoon-env" + } + } + ], + "env": [ + { + "name": "LAGOON_GIT_SHA", + "value": "0000000000000000000000000000000000000000" + }, + { + "name": "SERVICE_NAME", + "value": "node" + } + ], + "resources": { + "requests": { + "cpu": "10m", + "memory": "10Mi" + } + }, + "volumeMounts": [ + { + "name": "lagoon-sshkey", + "readOnly": true, + "mountPath": "/var/run/secrets/lagoon/sshkey/" + } + ], + "imagePullPolicy": "Always", + "securityContext": {} + } + ], + "restartPolicy": "Never", + "imagePullSecrets": [ + { + "name": "lagoon-internal-registry-secret" + } + ], + "priorityClassName": "lagoon-priority-production", + "dnsConfig": { + "options": [ + { + "name": "timeout", + "value": "60" + }, + { + "name": "attempts", + "value": "10" + } + ] + }, + "enableServiceLinks": false + } + } + } + }, + "successfulJobsHistoryLimit": 0, + "failedJobsHistoryLimit": 1 + }, + "status": {} + } + ] + }, + "ingress": { + "metadata": {}, + "items": [ + { + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example.com", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "activestandby.lagoon.sh/migrate": "false", + "app.kubernetes.io/instance": "example.com", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "custom-ingress", + "lagoon.sh/autogenerated": "false", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/primaryIngress": "true", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "example.com", + "lagoon.sh/service-type": "custom-ingress", + "lagoon.sh/template": "custom-ingress-0.1.0" + }, + "annotations": { + "fastly.amazee.io/service-id": "service-id", + "fastly.amazee.io/watch": "true", + "idling.amazee.io/disable-request-verification": "false", + "ingress.kubernetes.io/ssl-redirect": "true", + "kubernetes.io/tls-acme": "true", + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x", + "monitor.stakater.com/enabled": "true", + "monitor.stakater.com/overridePath": "/", + "nginx.ingress.kubernetes.io/ssl-redirect": "true", + "uptimerobot.monitor.stakater.com/alert-contacts": "alertcontact", + "uptimerobot.monitor.stakater.com/interval": "60", + "uptimerobot.monitor.stakater.com/status-pages": "statuspageid" + } + }, + "spec": { + "tls": [ + { + "hosts": [ + "example.com" + ], + "secretName": "example.com-tls" + } + ], + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/", + "pathType": "Prefix", + "backend": { + "service": { + "name": "node", + "port": { + "name": "http" + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "node", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "autogenerated-ingress", + "lagoon.sh/autogenerated": "true", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "node", + "lagoon.sh/template": "autogenerated-ingress-0.1.0" + }, + "annotations": { + "fastly.amazee.io/watch": "false", + "idling.amazee.io/disable-request-verification": "false", + "ingress.kubernetes.io/ssl-redirect": "true", + "kubernetes.io/tls-acme": "true", + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x", + "monitor.stakater.com/enabled": "false", + "nginx.ingress.kubernetes.io/server-snippet": "add_header X-Robots-Tag \"noindex, nofollow\";\n", + "nginx.ingress.kubernetes.io/ssl-redirect": "true" + } + }, + "spec": { + "tls": [ + { + "hosts": [ + "node-example-project-main.example.com" + ], + "secretName": "node-tls" + } + ], + "rules": [ + { + "host": "node-example-project-main.example.com", + "http": { + "paths": [ + { + "path": "/", + "pathType": "Prefix", + "backend": { + "service": { + "name": "node", + "port": { + "name": "http" + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } + } + ] + }, + "services": { + "metadata": {}, + "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "node", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "basic", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic", + "lagoon.sh/template": "basic-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "ports": [ + { + "name": "tcp-1234", + "protocol": "TCP", + "port": 1234, + "targetPort": "tcp-1234" + }, + { + "name": "tcp-8191", + "protocol": "TCP", + "port": 8191, + "targetPort": "tcp-8191" + }, + { + "name": "udp-9001", + "protocol": "UDP", + "port": 9001, + "targetPort": "udp-9001" + } + ], + "selector": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/name": "basic" + } + }, + "status": { + "loadBalancer": {} + } + } + ] + }, + "secrets": { + "metadata": {}, + "items": [] + }, + "pvcs": { + "metadata": {}, + "items": [] + }, + "schedulesv1": { + "metadata": {}, + "items": [] + }, + "schedulesv1alpha1": { + "metadata": {}, + "items": [ + { + "kind": "Schedule", + "apiVersion": "backup.appuio.ch/v1alpha1", + "metadata": { + "name": "k8up-lagoon-backup-schedule", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "k8up-lagoon-backup-schedule", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "k8up-schedule", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "k8up-lagoon-backup-schedule", + "lagoon.sh/service-type": "k8up-schedule", + "lagoon.sh/template": "k8up-schedule-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "backup": { + "resources": {}, + "schedule": "48 22 * * *" + }, + "check": { + "resources": {}, + "schedule": "48 5 * * 1" + }, + "prune": { + "resources": {}, + "retention": { + "keepDaily": 7, + "keepWeekly": 6 + }, + "schedule": "48 3 * * 0" + }, + "backend": { + "repoPasswordSecretRef": { + "name": "baas-repo-pw", + "key": "repo-pw" + }, + "s3": { + "bucket": "baas-example-project" + } + }, + "resourceRequirementsTemplate": {} + }, + "status": {} + } + ] + }, + "prebackuppodsv1": { + "metadata": {}, + "items": [] + }, + "prebackuppodsv1alpha1": { + "metadata": {}, + "items": [ + { + "kind": "PreBackupPod", + "apiVersion": "backup.appuio.ch/v1alpha1", + "metadata": { + "name": "mariadb-prebackuppod", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "mariadb", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "mariadb-dbaas", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "mariadb", + "lagoon.sh/service-type": "mariadb-dbaas", + "prebackuppod": "mariadb" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "backupCommand": "/bin/sh -c \"if [ ! -z $BACKUP_DB_READREPLICA_HOSTS ]; then BACKUP_DB_HOST=$(echo $BACKUP_DB_READREPLICA_HOSTS | cut -d ',' -f1); fi \u0026\u0026 dump=$(mktemp) \u0026\u0026 mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --no-data --no-tablespaces -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE \u003e $dump \u0026\u0026 mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --ignore-table=$BACKUP_DB_DATABASE.watchdog --no-create-info --no-tablespaces --skip-triggers -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE \u003e\u003e $dump \u0026\u0026 cat $dump \u0026\u0026 rm $dump\"\n", + "fileExtension": ".mariadb.sql", + "pod": { + "metadata": { + "creationTimestamp": null + }, + "spec": { + "containers": [ + { + "name": "mariadb-prebackuppod", + "image": "imagecache.example.com/uselagoon/database-tools:latest", + "args": [ + "sleep", + "infinity" + ], + "env": [ + { + "name": "BACKUP_DB_HOST", + "valueFrom": { + "configMapKeyRef": { + "name": "lagoon-env", + "key": "MARIADB_HOST" + } + } + }, + { + "name": "BACKUP_DB_USERNAME", + "valueFrom": { + "configMapKeyRef": { + "name": "lagoon-env", + "key": "MARIADB_USERNAME" + } + } + }, + { + "name": "BACKUP_DB_PASSWORD", + "valueFrom": { + "configMapKeyRef": { + "name": "lagoon-env", + "key": "MARIADB_PASSWORD" + } + } + }, + { + "name": "BACKUP_DB_DATABASE", + "valueFrom": { + "configMapKeyRef": { + "name": "lagoon-env", + "key": "MARIADB_DATABASE" + } + } + } + ], + "resources": {}, + "imagePullPolicy": "Always" + } + ] + } + } + } + } + ] + }, + "mariadbconsumers": { + "metadata": {}, + "items": [] + }, + "mongodbconsumers": { + "metadata": {}, + "items": [] + }, + "postgresqlconsumers": { + "metadata": {}, + "items": [] + } +} \ No newline at end of file diff --git a/internal/collector/testdata/json-result/result-2.json b/internal/collector/testdata/json-result/result-2.json new file mode 100644 index 00000000..6c004f3b --- /dev/null +++ b/internal/collector/testdata/json-result/result-2.json @@ -0,0 +1,440 @@ +{ + "deployments": { + "metadata": {}, + "items": [ + { + "kind": "Deployment", + "apiVersion": "apps/v1", + "metadata": { + "name": "node", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "basic-persistent", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic-persistent", + "lagoon.sh/template": "basic-persistent-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "replicas": 1, + "selector": { + "matchLabels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/name": "basic-persistent" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "basic-persistent", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic-persistent", + "lagoon.sh/template": "basic-persistent-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/configMapSha": "abcdefg1234567890", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "volumes": [ + { + "name": "custom-config", + "persistentVolumeClaim": { + "claimName": "custom-config" + } + }, + { + "name": "custom-files", + "persistentVolumeClaim": { + "claimName": "custom-files" + } + }, + { + "name": "node", + "persistentVolumeClaim": { + "claimName": "node" + } + } + ], + "containers": [ + { + "name": "basic", + "image": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "ports": [ + { + "name": "http", + "containerPort": 3000, + "protocol": "TCP" + } + ], + "envFrom": [ + { + "configMapRef": { + "name": "lagoon-env" + } + } + ], + "env": [ + { + "name": "LAGOON_GIT_SHA", + "value": "abcdefg123456" + }, + { + "name": "CRONJOBS" + }, + { + "name": "SERVICE_NAME", + "value": "node" + } + ], + "resources": { + "requests": { + "cpu": "10m", + "memory": "10Mi" + } + }, + "volumeMounts": [ + { + "name": "custom-config", + "mountPath": "/config" + }, + { + "name": "custom-files", + "mountPath": "/app/files/" + }, + { + "name": "node", + "mountPath": "/data" + } + ], + "livenessProbe": { + "tcpSocket": { + "port": 3000 + }, + "initialDelaySeconds": 60, + "timeoutSeconds": 10 + }, + "readinessProbe": { + "tcpSocket": { + "port": 3000 + }, + "initialDelaySeconds": 1, + "timeoutSeconds": 1 + }, + "imagePullPolicy": "Always", + "securityContext": {} + } + ], + "imagePullSecrets": [ + { + "name": "lagoon-internal-registry-secret" + } + ], + "priorityClassName": "lagoon-priority-production", + "enableServiceLinks": false + } + }, + "strategy": {} + }, + "status": {} + } + ] + }, + "cronjobs": { + "metadata": {}, + "items": [] + }, + "ingress": { + "metadata": {}, + "items": [ + { + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "example.com", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "activestandby.lagoon.sh/migrate": "false", + "app.kubernetes.io/instance": "example.com", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "custom-ingress", + "lagoon.sh/autogenerated": "false", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/primaryIngress": "true", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "example.com", + "lagoon.sh/service-type": "custom-ingress", + "lagoon.sh/template": "custom-ingress-0.1.0" + }, + "annotations": { + "fastly.amazee.io/service-id": "service-id", + "fastly.amazee.io/watch": "true", + "idling.amazee.io/disable-request-verification": "false", + "ingress.kubernetes.io/ssl-redirect": "true", + "kubernetes.io/tls-acme": "true", + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x", + "monitor.stakater.com/enabled": "true", + "monitor.stakater.com/overridePath": "/", + "nginx.ingress.kubernetes.io/ssl-redirect": "true", + "uptimerobot.monitor.stakater.com/alert-contacts": "alertcontact", + "uptimerobot.monitor.stakater.com/interval": "60", + "uptimerobot.monitor.stakater.com/status-pages": "statuspageid" + } + }, + "spec": { + "tls": [ + { + "hosts": [ + "example.com" + ], + "secretName": "example.com-tls" + } + ], + "rules": [ + { + "host": "example.com", + "http": { + "paths": [ + { + "path": "/", + "pathType": "Prefix", + "backend": { + "service": { + "name": "node", + "port": { + "name": "http" + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } + }, + { + "kind": "Ingress", + "apiVersion": "networking.k8s.io/v1", + "metadata": { + "name": "node", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "autogenerated-ingress", + "lagoon.sh/autogenerated": "true", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "node", + "lagoon.sh/template": "autogenerated-ingress-0.1.0" + }, + "annotations": { + "fastly.amazee.io/watch": "false", + "idling.amazee.io/disable-request-verification": "false", + "ingress.kubernetes.io/ssl-redirect": "true", + "kubernetes.io/tls-acme": "true", + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x", + "monitor.stakater.com/enabled": "false", + "nginx.ingress.kubernetes.io/server-snippet": "add_header X-Robots-Tag \"noindex, nofollow\";\n", + "nginx.ingress.kubernetes.io/ssl-redirect": "true" + } + }, + "spec": { + "tls": [ + { + "hosts": [ + "node-example-project-main.example.com" + ], + "secretName": "node-tls" + } + ], + "rules": [ + { + "host": "node-example-project-main.example.com", + "http": { + "paths": [ + { + "path": "/", + "pathType": "Prefix", + "backend": { + "service": { + "name": "node", + "port": { + "name": "http" + } + } + } + } + ] + } + } + ] + }, + "status": { + "loadBalancer": {} + } + } + ] + }, + "services": { + "metadata": {}, + "items": [ + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "node", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "basic-persistent", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic-persistent", + "lagoon.sh/template": "basic-persistent-0.1.0" + }, + "annotations": { + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "ports": [ + { + "name": "http", + "protocol": "TCP", + "port": 3000, + "targetPort": "http" + } + ], + "selector": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/name": "basic-persistent" + } + }, + "status": { + "loadBalancer": {} + } + } + ] + }, + "secrets": { + "metadata": {}, + "items": [] + }, + "pvcs": { + "metadata": {}, + "items": [ + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "node", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "node", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "basic-persistent", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service": "node", + "lagoon.sh/service-type": "basic-persistent", + "lagoon.sh/template": "basic-persistent-0.1.0" + }, + "annotations": { + "k8up.io/backup": "true", + "k8up.syn.tools/backup": "true", + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "accessModes": [ + "ReadWriteMany" + ], + "resources": { + "requests": { + "storage": "5Gi" + } + }, + "storageClassName": "bulk" + }, + "status": {} + } + ] + }, + "schedulesv1": { + "metadata": {}, + "items": [] + }, + "schedulesv1alpha1": { + "metadata": {}, + "items": [] + }, + "prebackuppodsv1": { + "metadata": {}, + "items": [] + }, + "prebackuppodsv1alpha1": { + "metadata": {}, + "items": [] + }, + "mariadbconsumers": { + "metadata": {}, + "items": [] + }, + "mongodbconsumers": { + "metadata": {}, + "items": [] + }, + "postgresqlconsumers": { + "metadata": {}, + "items": [] + } +} \ No newline at end of file diff --git a/internal/collector/testdata/result/result-1/lagoon-cronjobs.yaml b/internal/collector/testdata/result/result-1/lagoon-cronjobs.yaml new file mode 100644 index 00000000..50c2813f --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-cronjobs.yaml @@ -0,0 +1,93 @@ +items: +- apiVersion: batch/v1 + kind: CronJob + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: cronjob-node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: cronjob-basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: cronjob-node-env + namespace: example-project-main + resourceVersion: "1" + spec: + concurrencyPolicy: Forbid + failedJobsHistoryLimit: 1 + jobTemplate: + metadata: + creationTimestamp: null + spec: + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: cronjob-node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: cronjob-basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + spec: + containers: + - command: + - /lagoon/cronjob.sh + - env + env: + - name: LAGOON_GIT_SHA + value: "0000000000000000000000000000000000000000" + - name: SERVICE_NAME + value: node + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + name: cronjob-node-env + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + volumeMounts: + - mountPath: /var/run/secrets/lagoon/sshkey/ + name: lagoon-sshkey + readOnly: true + dnsConfig: + options: + - name: timeout + value: "60" + - name: attempts + value: "10" + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + restartPolicy: Never + volumes: + - name: lagoon-sshkey + secret: + defaultMode: 420 + secretName: lagoon-sshkey + schedule: 18,48 * * * * + startingDeadlineSeconds: 240 + successfulJobsHistoryLimit: 0 + status: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-deployments.yaml b/internal/collector/testdata/result/result-1/lagoon-deployments.yaml new file mode 100644 index 00000000..608eef36 --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-deployments.yaml @@ -0,0 +1,96 @@ +items: +- apiVersion: apps/v1 + kind: Deployment + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: node + namespace: example-project-main + resourceVersion: "1" + spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic + strategy: {} + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + spec: + containers: + - env: + - name: LAGOON_GIT_SHA + value: abcdefg123456 + - name: CRONJOBS + - name: SERVICE_NAME + value: node + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 60 + tcpSocket: + port: 1234 + timeoutSeconds: 10 + name: basic + ports: + - containerPort: 1234 + name: tcp-1234 + protocol: TCP + - containerPort: 8191 + name: tcp-8191 + protocol: TCP + - containerPort: 9001 + name: udp-9001 + protocol: UDP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 1234 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + - name: lagoon-private-registry-dockerhub + - name: lagoon-private-registry-my-custom-registry + - name: lagoon-private-registry-my-hardcode-registry + - name: lagoon-private-registry-my-other-registry + priorityClassName: lagoon-priority-production + status: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-ingress.yaml b/internal/collector/testdata/result/result-1/lagoon-ingress.yaml new file mode 100644 index 00000000..e12e5443 --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-ingress.yaml @@ -0,0 +1,103 @@ +items: +- apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + annotations: + fastly.amazee.io/service-id: service-id + fastly.amazee.io/watch: "true" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "true" + monitor.stakater.com/overridePath: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + uptimerobot.monitor.stakater.com/alert-contacts: alertcontact + uptimerobot.monitor.stakater.com/interval: "60" + uptimerobot.monitor.stakater.com/status-pages: statuspageid + creationTimestamp: null + labels: + activestandby.lagoon.sh/migrate: "false" + app.kubernetes.io/instance: example.com + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: custom-ingress + lagoon.sh/autogenerated: "false" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/primaryIngress: "true" + lagoon.sh/project: example-project + lagoon.sh/service: example.com + lagoon.sh/service-type: custom-ingress + lagoon.sh/template: custom-ingress-0.1.0 + name: example.com + namespace: example-project-main + resourceVersion: "1" + spec: + rules: + - host: example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - example.com + secretName: example.com-tls + status: + loadBalancer: {} +- apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + annotations: + fastly.amazee.io/watch: "false" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "false" + nginx.ingress.kubernetes.io/server-snippet: | + add_header X-Robots-Tag "noindex, nofollow"; + nginx.ingress.kubernetes.io/ssl-redirect: "true" + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: autogenerated-ingress + lagoon.sh/autogenerated: "true" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: node + lagoon.sh/template: autogenerated-ingress-0.1.0 + name: node + namespace: example-project-main + resourceVersion: "1" + spec: + rules: + - host: node-example-project-main.example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - node-example-project-main.example.com + secretName: node-tls + status: + loadBalancer: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-mariadb-consumers.yaml b/internal/collector/testdata/result/result-1/lagoon-mariadb-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-mariadb-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-mongodb-consumers.yaml b/internal/collector/testdata/result/result-1/lagoon-mongodb-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-mongodb-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-postgres-consumers.yaml b/internal/collector/testdata/result/result-1/lagoon-postgres-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-postgres-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1.yaml b/internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1alpha1.yaml b/internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1alpha1.yaml new file mode 100644 index 00000000..7203b186 --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-prebackuppods-v1alpha1.yaml @@ -0,0 +1,60 @@ +items: +- apiVersion: backup.appuio.ch/v1alpha1 + kind: PreBackupPod + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: mariadb + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: mariadb-dbaas + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: mariadb + lagoon.sh/service-type: mariadb-dbaas + prebackuppod: mariadb + name: mariadb-prebackuppod + namespace: example-project-main + resourceVersion: "1" + spec: + backupCommand: | + /bin/sh -c "if [ ! -z $BACKUP_DB_READREPLICA_HOSTS ]; then BACKUP_DB_HOST=$(echo $BACKUP_DB_READREPLICA_HOSTS | cut -d ',' -f1); fi && dump=$(mktemp) && mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --no-data --no-tablespaces -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE > $dump && mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --ignore-table=$BACKUP_DB_DATABASE.watchdog --no-create-info --no-tablespaces --skip-triggers -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE >> $dump && cat $dump && rm $dump" + fileExtension: .mariadb.sql + pod: + metadata: + creationTimestamp: null + spec: + containers: + - args: + - sleep + - infinity + env: + - name: BACKUP_DB_HOST + valueFrom: + configMapKeyRef: + key: MARIADB_HOST + name: lagoon-env + - name: BACKUP_DB_USERNAME + valueFrom: + configMapKeyRef: + key: MARIADB_USERNAME + name: lagoon-env + - name: BACKUP_DB_PASSWORD + valueFrom: + configMapKeyRef: + key: MARIADB_PASSWORD + name: lagoon-env + - name: BACKUP_DB_DATABASE + valueFrom: + configMapKeyRef: + key: MARIADB_DATABASE + name: lagoon-env + image: imagecache.example.com/uselagoon/database-tools:latest + imagePullPolicy: Always + name: mariadb-prebackuppod + resources: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-pvcs.yaml b/internal/collector/testdata/result/result-1/lagoon-pvcs.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-pvcs.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-schedules-v1.yaml b/internal/collector/testdata/result/result-1/lagoon-schedules-v1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-schedules-v1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-schedules-v1alpha1.yaml b/internal/collector/testdata/result/result-1/lagoon-schedules-v1alpha1.yaml new file mode 100644 index 00000000..30606822 --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-schedules-v1alpha1.yaml @@ -0,0 +1,44 @@ +items: +- apiVersion: backup.appuio.ch/v1alpha1 + kind: Schedule + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: k8up-lagoon-backup-schedule + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: k8up-schedule + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: k8up-lagoon-backup-schedule + lagoon.sh/service-type: k8up-schedule + lagoon.sh/template: k8up-schedule-0.1.0 + name: k8up-lagoon-backup-schedule + namespace: example-project-main + resourceVersion: "1" + spec: + backend: + repoPasswordSecretRef: + key: repo-pw + name: baas-repo-pw + s3: + bucket: baas-example-project + backup: + resources: {} + schedule: 48 22 * * * + check: + resources: {} + schedule: 48 5 * * 1 + prune: + resources: {} + retention: + keepDaily: 7 + keepWeekly: 6 + schedule: 48 3 * * 0 + resourceRequirementsTemplate: {} + status: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-secrets.yaml b/internal/collector/testdata/result/result-1/lagoon-secrets.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-secrets.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-1/lagoon-services.yaml b/internal/collector/testdata/result/result-1/lagoon-services.yaml new file mode 100644 index 00000000..a4b933eb --- /dev/null +++ b/internal/collector/testdata/result/result-1/lagoon-services.yaml @@ -0,0 +1,42 @@ +items: +- apiVersion: v1 + kind: Service + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: node + namespace: example-project-main + resourceVersion: "1" + spec: + ports: + - name: tcp-1234 + port: 1234 + protocol: TCP + targetPort: tcp-1234 + - name: tcp-8191 + port: 8191 + protocol: TCP + targetPort: tcp-8191 + - name: udp-9001 + port: 9001 + protocol: UDP + targetPort: udp-9001 + selector: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic + status: + loadBalancer: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-cronjobs.yaml b/internal/collector/testdata/result/result-2/lagoon-cronjobs.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-cronjobs.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-deployments.yaml b/internal/collector/testdata/result/result-2/lagoon-deployments.yaml new file mode 100644 index 00000000..4bdf3184 --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-deployments.yaml @@ -0,0 +1,103 @@ +items: +- apiVersion: apps/v1 + kind: Deployment + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic-persistent + lagoon.sh/template: basic-persistent-0.1.0 + name: node + namespace: example-project-main + resourceVersion: "1" + spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic-persistent + strategy: {} + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic-persistent + lagoon.sh/template: basic-persistent-0.1.0 + spec: + containers: + - env: + - name: LAGOON_GIT_SHA + value: abcdefg123456 + - name: CRONJOBS + - name: SERVICE_NAME + value: node + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 60 + tcpSocket: + port: 3000 + timeoutSeconds: 10 + name: basic + ports: + - containerPort: 3000 + name: http + protocol: TCP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 3000 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + volumeMounts: + - mountPath: /config + name: custom-config + - mountPath: /app/files/ + name: custom-files + - mountPath: /data + name: node + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + volumes: + - name: custom-config + persistentVolumeClaim: + claimName: custom-config + - name: custom-files + persistentVolumeClaim: + claimName: custom-files + - name: node + persistentVolumeClaim: + claimName: node + status: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-ingress.yaml b/internal/collector/testdata/result/result-2/lagoon-ingress.yaml new file mode 100644 index 00000000..e12e5443 --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-ingress.yaml @@ -0,0 +1,103 @@ +items: +- apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + annotations: + fastly.amazee.io/service-id: service-id + fastly.amazee.io/watch: "true" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "true" + monitor.stakater.com/overridePath: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + uptimerobot.monitor.stakater.com/alert-contacts: alertcontact + uptimerobot.monitor.stakater.com/interval: "60" + uptimerobot.monitor.stakater.com/status-pages: statuspageid + creationTimestamp: null + labels: + activestandby.lagoon.sh/migrate: "false" + app.kubernetes.io/instance: example.com + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: custom-ingress + lagoon.sh/autogenerated: "false" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/primaryIngress: "true" + lagoon.sh/project: example-project + lagoon.sh/service: example.com + lagoon.sh/service-type: custom-ingress + lagoon.sh/template: custom-ingress-0.1.0 + name: example.com + namespace: example-project-main + resourceVersion: "1" + spec: + rules: + - host: example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - example.com + secretName: example.com-tls + status: + loadBalancer: {} +- apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + annotations: + fastly.amazee.io/watch: "false" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "false" + nginx.ingress.kubernetes.io/server-snippet: | + add_header X-Robots-Tag "noindex, nofollow"; + nginx.ingress.kubernetes.io/ssl-redirect: "true" + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: autogenerated-ingress + lagoon.sh/autogenerated: "true" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: node + lagoon.sh/template: autogenerated-ingress-0.1.0 + name: node + namespace: example-project-main + resourceVersion: "1" + spec: + rules: + - host: node-example-project-main.example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - node-example-project-main.example.com + secretName: node-tls + status: + loadBalancer: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-mariadb-consumers.yaml b/internal/collector/testdata/result/result-2/lagoon-mariadb-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-mariadb-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-mongodb-consumers.yaml b/internal/collector/testdata/result/result-2/lagoon-mongodb-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-mongodb-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-postgres-consumers.yaml b/internal/collector/testdata/result/result-2/lagoon-postgres-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-postgres-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1.yaml b/internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1alpha1.yaml b/internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1alpha1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-prebackuppods-v1alpha1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-schedules-v1.yaml b/internal/collector/testdata/result/result-2/lagoon-schedules-v1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-schedules-v1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-schedules-v1alpha1.yaml b/internal/collector/testdata/result/result-2/lagoon-schedules-v1alpha1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-schedules-v1alpha1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-secrets.yaml b/internal/collector/testdata/result/result-2/lagoon-secrets.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-secrets.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-2/lagoon-services.yaml b/internal/collector/testdata/result/result-2/lagoon-services.yaml new file mode 100644 index 00000000..6d383ee6 --- /dev/null +++ b/internal/collector/testdata/result/result-2/lagoon-services.yaml @@ -0,0 +1,34 @@ +items: +- apiVersion: v1 + kind: Service + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic-persistent + lagoon.sh/template: basic-persistent-0.1.0 + name: node + namespace: example-project-main + resourceVersion: "1" + spec: + ports: + - name: http + port: 3000 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic-persistent + status: + loadBalancer: {} +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-cronjobs.yaml b/internal/collector/testdata/result/result-empty/lagoon-cronjobs.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-cronjobs.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-deployments.yaml b/internal/collector/testdata/result/result-empty/lagoon-deployments.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-deployments.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-ingress.yaml b/internal/collector/testdata/result/result-empty/lagoon-ingress.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-ingress.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-mariadb-consumers.yaml b/internal/collector/testdata/result/result-empty/lagoon-mariadb-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-mariadb-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-mongodb-consumers.yaml b/internal/collector/testdata/result/result-empty/lagoon-mongodb-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-mongodb-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-postgres-consumers.yaml b/internal/collector/testdata/result/result-empty/lagoon-postgres-consumers.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-postgres-consumers.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1.yaml b/internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1alpha1.yaml b/internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1alpha1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-prebackuppods-v1alpha1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-pvcs.yaml b/internal/collector/testdata/result/result-empty/lagoon-pvcs.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-pvcs.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-schedules-v1.yaml b/internal/collector/testdata/result/result-empty/lagoon-schedules-v1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-schedules-v1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-schedules-v1alpha1.yaml b/internal/collector/testdata/result/result-empty/lagoon-schedules-v1alpha1.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-schedules-v1alpha1.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-secrets.yaml b/internal/collector/testdata/result/result-empty/lagoon-secrets.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-secrets.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/result/result-empty/lagoon-services.yaml b/internal/collector/testdata/result/result-empty/lagoon-services.yaml new file mode 100644 index 00000000..d045881a --- /dev/null +++ b/internal/collector/testdata/result/result-empty/lagoon-services.yaml @@ -0,0 +1,2 @@ +items: [] +metadata: {} diff --git a/internal/collector/testdata/seed/seed-1/cronjob-cronjob-node-env.yaml b/internal/collector/testdata/seed/seed-1/cronjob-cronjob-node-env.yaml new file mode 100644 index 00000000..06d40329 --- /dev/null +++ b/internal/collector/testdata/seed/seed-1/cronjob-cronjob-node-env.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: cronjob-node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: cronjob-basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: cronjob-node-env +spec: + concurrencyPolicy: Forbid + failedJobsHistoryLimit: 1 + jobTemplate: + metadata: + creationTimestamp: null + spec: + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: cronjob-node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: cronjob-basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + spec: + containers: + - command: + - /lagoon/cronjob.sh + - env + env: + - name: LAGOON_GIT_SHA + value: "0000000000000000000000000000000000000000" + - name: SERVICE_NAME + value: node + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + name: cronjob-node-env + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + volumeMounts: + - mountPath: /var/run/secrets/lagoon/sshkey/ + name: lagoon-sshkey + readOnly: true + dnsConfig: + options: + - name: timeout + value: "60" + - name: attempts + value: "10" + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + restartPolicy: Never + volumes: + - name: lagoon-sshkey + secret: + defaultMode: 420 + secretName: lagoon-sshkey + schedule: 18,48 * * * * + startingDeadlineSeconds: 240 + successfulJobsHistoryLimit: 0 +status: {} diff --git a/internal/collector/testdata/seed/seed-1/deployment-node.yaml b/internal/collector/testdata/seed/seed-1/deployment-node.yaml new file mode 100644 index 00000000..5684eb16 --- /dev/null +++ b/internal/collector/testdata/seed/seed-1/deployment-node.yaml @@ -0,0 +1,93 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: node +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic + strategy: {} + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + spec: + containers: + - env: + - name: LAGOON_GIT_SHA + value: abcdefg123456 + - name: CRONJOBS + - name: SERVICE_NAME + value: node + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 60 + tcpSocket: + port: 1234 + timeoutSeconds: 10 + name: basic + ports: + - containerPort: 1234 + name: tcp-1234 + protocol: TCP + - containerPort: 8191 + name: tcp-8191 + protocol: TCP + - containerPort: 9001 + name: udp-9001 + protocol: UDP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 1234 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + - name: lagoon-private-registry-dockerhub + - name: lagoon-private-registry-my-custom-registry + - name: lagoon-private-registry-my-hardcode-registry + - name: lagoon-private-registry-my-other-registry + priorityClassName: lagoon-priority-production +status: {} diff --git a/internal/collector/testdata/seed/seed-1/ingress-example.com.yaml b/internal/collector/testdata/seed/seed-1/ingress-example.com.yaml new file mode 100644 index 00000000..bb27ab4d --- /dev/null +++ b/internal/collector/testdata/seed/seed-1/ingress-example.com.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + fastly.amazee.io/service-id: service-id + fastly.amazee.io/watch: "true" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "true" + monitor.stakater.com/overridePath: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + uptimerobot.monitor.stakater.com/alert-contacts: alertcontact + uptimerobot.monitor.stakater.com/interval: "60" + uptimerobot.monitor.stakater.com/status-pages: statuspageid + creationTimestamp: null + labels: + activestandby.lagoon.sh/migrate: "false" + app.kubernetes.io/instance: example.com + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: custom-ingress + lagoon.sh/autogenerated: "false" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/primaryIngress: "true" + lagoon.sh/project: example-project + lagoon.sh/service: example.com + lagoon.sh/service-type: custom-ingress + lagoon.sh/template: custom-ingress-0.1.0 + name: example.com +spec: + rules: + - host: example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - example.com + secretName: example.com-tls +status: + loadBalancer: {} diff --git a/internal/collector/testdata/seed/seed-1/ingress-node.yaml b/internal/collector/testdata/seed/seed-1/ingress-node.yaml new file mode 100644 index 00000000..577f24f9 --- /dev/null +++ b/internal/collector/testdata/seed/seed-1/ingress-node.yaml @@ -0,0 +1,47 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + fastly.amazee.io/watch: "false" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "false" + nginx.ingress.kubernetes.io/server-snippet: | + add_header X-Robots-Tag "noindex, nofollow"; + nginx.ingress.kubernetes.io/ssl-redirect: "true" + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: autogenerated-ingress + lagoon.sh/autogenerated: "true" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: node + lagoon.sh/template: autogenerated-ingress-0.1.0 + name: node +spec: + rules: + - host: node-example-project-main.example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - node-example-project-main.example.com + secretName: node-tls +status: + loadBalancer: {} diff --git a/internal/collector/testdata/seed/seed-1/k8up-lagoon-backup-schedule.yaml b/internal/collector/testdata/seed/seed-1/k8up-lagoon-backup-schedule.yaml new file mode 100644 index 00000000..69632bcf --- /dev/null +++ b/internal/collector/testdata/seed/seed-1/k8up-lagoon-backup-schedule.yaml @@ -0,0 +1,41 @@ +--- +apiVersion: backup.appuio.ch/v1alpha1 +kind: Schedule +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: k8up-lagoon-backup-schedule + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: k8up-schedule + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: k8up-lagoon-backup-schedule + lagoon.sh/service-type: k8up-schedule + lagoon.sh/template: k8up-schedule-0.1.0 + name: k8up-lagoon-backup-schedule +spec: + backend: + repoPasswordSecretRef: + key: repo-pw + name: baas-repo-pw + s3: + bucket: baas-example-project + backup: + resources: {} + schedule: 48 22 * * * + check: + resources: {} + schedule: 48 5 * * 1 + prune: + resources: {} + retention: + keepDaily: 7 + keepWeekly: 6 + schedule: 48 3 * * 0 + resourceRequirementsTemplate: {} +status: {} diff --git a/internal/collector/testdata/seed/seed-1/prebackuppod-mariadb.yaml b/internal/collector/testdata/seed/seed-1/prebackuppod-mariadb.yaml new file mode 100644 index 00000000..7212b498 --- /dev/null +++ b/internal/collector/testdata/seed/seed-1/prebackuppod-mariadb.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: backup.appuio.ch/v1alpha1 +kind: PreBackupPod +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: mariadb + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: mariadb-dbaas + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: mariadb + lagoon.sh/service-type: mariadb-dbaas + prebackuppod: mariadb + name: mariadb-prebackuppod +spec: + backupCommand: | + /bin/sh -c "if [ ! -z $BACKUP_DB_READREPLICA_HOSTS ]; then BACKUP_DB_HOST=$(echo $BACKUP_DB_READREPLICA_HOSTS | cut -d ',' -f1); fi && dump=$(mktemp) && mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --no-data --no-tablespaces -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE > $dump && mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --ignore-table=$BACKUP_DB_DATABASE.watchdog --no-create-info --no-tablespaces --skip-triggers -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE >> $dump && cat $dump && rm $dump" + fileExtension: .mariadb.sql + pod: + metadata: {} + spec: + containers: + - args: + - sleep + - infinity + env: + - name: BACKUP_DB_HOST + valueFrom: + configMapKeyRef: + key: MARIADB_HOST + name: lagoon-env + - name: BACKUP_DB_USERNAME + valueFrom: + configMapKeyRef: + key: MARIADB_USERNAME + name: lagoon-env + - name: BACKUP_DB_PASSWORD + valueFrom: + configMapKeyRef: + key: MARIADB_PASSWORD + name: lagoon-env + - name: BACKUP_DB_DATABASE + valueFrom: + configMapKeyRef: + key: MARIADB_DATABASE + name: lagoon-env + image: imagecache.example.com/uselagoon/database-tools:latest + imagePullPolicy: Always + name: mariadb-prebackuppod + resources: {} diff --git a/internal/collector/testdata/seed/seed-1/service-node.yaml b/internal/collector/testdata/seed/seed-1/service-node.yaml new file mode 100644 index 00000000..6b286993 --- /dev/null +++ b/internal/collector/testdata/seed/seed-1/service-node.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: node +spec: + ports: + - name: tcp-1234 + port: 1234 + protocol: TCP + targetPort: tcp-1234 + - name: tcp-8191 + port: 8191 + protocol: TCP + targetPort: tcp-8191 + - name: udp-9001 + port: 9001 + protocol: UDP + targetPort: udp-9001 + selector: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic +status: + loadBalancer: {} diff --git a/internal/collector/testdata/seed/seed-2/deployment-node.yaml b/internal/collector/testdata/seed/seed-2/deployment-node.yaml new file mode 100644 index 00000000..5567c6ba --- /dev/null +++ b/internal/collector/testdata/seed/seed-2/deployment-node.yaml @@ -0,0 +1,100 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic-persistent + lagoon.sh/template: basic-persistent-0.1.0 + name: node +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic-persistent + strategy: {} + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic-persistent + lagoon.sh/template: basic-persistent-0.1.0 + spec: + containers: + - env: + - name: LAGOON_GIT_SHA + value: abcdefg123456 + - name: CRONJOBS + - name: SERVICE_NAME + value: node + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 60 + tcpSocket: + port: 3000 + timeoutSeconds: 10 + name: basic + ports: + - containerPort: 3000 + name: http + protocol: TCP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 3000 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + volumeMounts: + - mountPath: /config + name: custom-config + - mountPath: /app/files/ + name: custom-files + - mountPath: /data + name: node + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + volumes: + - name: custom-config + persistentVolumeClaim: + claimName: custom-config + - name: custom-files + persistentVolumeClaim: + claimName: custom-files + - name: node + persistentVolumeClaim: + claimName: node +status: {} diff --git a/internal/collector/testdata/seed/seed-2/ingress-example.com.yaml b/internal/collector/testdata/seed/seed-2/ingress-example.com.yaml new file mode 100644 index 00000000..bb27ab4d --- /dev/null +++ b/internal/collector/testdata/seed/seed-2/ingress-example.com.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + fastly.amazee.io/service-id: service-id + fastly.amazee.io/watch: "true" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "true" + monitor.stakater.com/overridePath: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + uptimerobot.monitor.stakater.com/alert-contacts: alertcontact + uptimerobot.monitor.stakater.com/interval: "60" + uptimerobot.monitor.stakater.com/status-pages: statuspageid + creationTimestamp: null + labels: + activestandby.lagoon.sh/migrate: "false" + app.kubernetes.io/instance: example.com + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: custom-ingress + lagoon.sh/autogenerated: "false" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/primaryIngress: "true" + lagoon.sh/project: example-project + lagoon.sh/service: example.com + lagoon.sh/service-type: custom-ingress + lagoon.sh/template: custom-ingress-0.1.0 + name: example.com +spec: + rules: + - host: example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - example.com + secretName: example.com-tls +status: + loadBalancer: {} diff --git a/internal/collector/testdata/seed/seed-2/ingress-node.yaml b/internal/collector/testdata/seed/seed-2/ingress-node.yaml new file mode 100644 index 00000000..577f24f9 --- /dev/null +++ b/internal/collector/testdata/seed/seed-2/ingress-node.yaml @@ -0,0 +1,47 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + fastly.amazee.io/watch: "false" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "false" + nginx.ingress.kubernetes.io/server-snippet: | + add_header X-Robots-Tag "noindex, nofollow"; + nginx.ingress.kubernetes.io/ssl-redirect: "true" + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: autogenerated-ingress + lagoon.sh/autogenerated: "true" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: node + lagoon.sh/template: autogenerated-ingress-0.1.0 + name: node +spec: + rules: + - host: node-example-project-main.example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - node-example-project-main.example.com + secretName: node-tls +status: + loadBalancer: {} diff --git a/internal/collector/testdata/seed/seed-2/pvc-custom-config.yaml b/internal/collector/testdata/seed/seed-2/pvc-custom-config.yaml new file mode 100644 index 00000000..c1465784 --- /dev/null +++ b/internal/collector/testdata/seed/seed-2/pvc-custom-config.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + k8up.io/backup: "true" + k8up.syn.tools/backup: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: custom-config + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: config + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service-type: additional-volume + lagoon.sh/template: additional-volume-0.1.0 + name: custom-config +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi + storageClassName: bulk +status: {} diff --git a/internal/collector/testdata/seed/seed-2/pvc-custom-files.yaml b/internal/collector/testdata/seed/seed-2/pvc-custom-files.yaml new file mode 100644 index 00000000..dfe9d701 --- /dev/null +++ b/internal/collector/testdata/seed/seed-2/pvc-custom-files.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + k8up.io/backup: "true" + k8up.syn.tools/backup: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: custom-files + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: files + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service-type: additional-volume + lagoon.sh/template: additional-volume-0.1.0 + name: custom-files +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Gi + storageClassName: bulk +status: {} diff --git a/internal/collector/testdata/seed/seed-2/pvc-node.yaml b/internal/collector/testdata/seed/seed-2/pvc-node.yaml new file mode 100644 index 00000000..44cfd035 --- /dev/null +++ b/internal/collector/testdata/seed/seed-2/pvc-node.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + k8up.io/backup: "true" + k8up.syn.tools/backup: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic-persistent + lagoon.sh/template: basic-persistent-0.1.0 + name: node +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi + storageClassName: bulk +status: {} diff --git a/internal/collector/testdata/seed/seed-2/service-node.yaml b/internal/collector/testdata/seed/seed-2/service-node.yaml new file mode 100644 index 00000000..fa68a29f --- /dev/null +++ b/internal/collector/testdata/seed/seed-2/service-node.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: node + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic-persistent + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: node + lagoon.sh/service-type: basic-persistent + lagoon.sh/template: basic-persistent-0.1.0 + name: node +spec: + ports: + - name: http + port: 3000 + protocol: TCP + targetPort: http + selector: + app.kubernetes.io/instance: node + app.kubernetes.io/name: basic-persistent +status: + loadBalancer: {} diff --git a/internal/collector/testdata/seed/seed-empty/.gitkeep b/internal/collector/testdata/seed/seed-empty/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/internal/k8s/client.go b/internal/k8s/client.go new file mode 100644 index 00000000..58842045 --- /dev/null +++ b/internal/k8s/client.go @@ -0,0 +1,117 @@ +package k8s + +import ( + "context" + "fmt" + "os" + + mariadbv1 "github.com/amazeeio/dbaas-operator/apis/mariadb/v1" + mongodbv1 "github.com/amazeeio/dbaas-operator/apis/mongodb/v1" + postgresv1 "github.com/amazeeio/dbaas-operator/apis/postgres/v1" + k8upv1 "github.com/k8up-io/k8up/v2/api/v1" + k8upv1alpha1 "github.com/vshn/k8up/api/v1alpha1" + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + networkv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + client "sigs.k8s.io/controller-runtime/pkg/client" + ctrlfake "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/yaml" +) + +func NewClient() (client.Client, error) { + // read the serviceaccount deployer token first. + token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token") + if err != nil { + // read the legacy deployer token if for some reason the serviceaccount is not found. + token, err = os.ReadFile("/var/run/secrets/lagoon/deployer/token") + if err != nil { + return nil, err + } + } + // generate the rest config for the client. + config := &rest.Config{ + BearerToken: string(token), + Host: "https://kubernetes.default.svc", + TLSClientConfig: rest.TLSClientConfig{ + Insecure: true, + }, + } + // create the client using the rest config. + return client.New(config, client.Options{}) +} + +func NewFakeClient(namespace string) (client.Client, error) { + k8sScheme := runtime.NewScheme() + // any custom crds etc need to be added to the fake client so it knows about them + if err := mariadbv1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := mongodbv1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := postgresv1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := k8upv1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := k8upv1alpha1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := batchv1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := appsv1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := networkv1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + if err := corev1.AddToScheme(k8sScheme); err != nil { + return nil, err + } + clientBuilder := ctrlfake.NewClientBuilder() + clientBuilder = clientBuilder.WithScheme(k8sScheme) + + fakeClient := clientBuilder.Build() + ns := corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + err := fakeClient.Create(context.Background(), &ns) + if err != nil { + return nil, err + } + return fakeClient, nil +} + +func SeedFakeData(fakeClient client.Client, namespace string, seedDir string) error { + dir, err := os.ReadDir(seedDir) + if err != nil { + return fmt.Errorf("couldn't read directory %v: %v", seedDir, err) + } + for _, r := range dir { + if r.Name() == ".gitkeep" { + continue + } + seedFile := fmt.Sprintf("%s/%s", seedDir, r.Name()) + sfb, err := os.ReadFile(seedFile) + if err != nil { + return fmt.Errorf("couldn't read file %v: %v", seedFile, err) + } + u := &unstructured.Unstructured{} + yaml.Unmarshal(sfb, u) + u.SetNamespace(namespace) + err = fakeClient.Create(context.Background(), u) + if err != nil { + return err + } + } + return nil +} diff --git a/legacy/build-deploy-docker-compose.sh b/legacy/build-deploy-docker-compose.sh index 63ab0279..a819a267 100755 --- a/legacy/build-deploy-docker-compose.sh +++ b/legacy/build-deploy-docker-compose.sh @@ -144,6 +144,51 @@ function patchBuildStep() { ############################################## buildStartTime="$(date +"%Y-%m-%d %H:%M:%S")" +beginBuildStep "Initial Environment Collection" "collectEnvironment" + +############################################## +### COLLECT INFORMATION +############################################## + +# run the collector +ENVIRONMENT_DATA=$(build-deploy-tool collect environment) +# get the images currently used +DEPLOYMENTS=$(echo "$ENVIRONMENT_DATA" | jq -r '.deployments.items[]?.spec.template.spec.containers[].image') +touch /kubectl-build-deploy/current-images.yaml +for DEP_IMAGE in ${DEPLOYMENT_IMAGES} +do + # generate the images file used for templating here + if [[ "$DEP_IMAGE" =~ (.*\/)(.*)(@sha256:.*) ]] + then + COMPOSE_SERVICE=${BASH_REMATCH[2]} + fi + yq -i '.images.'$COMPOSE_SERVICE' = "'$DEP_IMAGE'"' /kubectl-build-deploy/current-images.yaml +done +cat /kubectl-build-deploy/current-images.yaml +# echo "$ENVIRONMENT_DATA" | jq -r '.cronjobs' +# echo "$ENVIRONMENT_DATA" | jq -r '.ingress' +# echo "$ENVIRONMENT_DATA" | jq -r '.services' +# echo "$ENVIRONMENT_DATA" | jq -r '.secrets' +# echo "$ENVIRONMENT_DATA" | jq -r '.pvcs' +# echo "$ENVIRONMENT_DATA" | jq -r '.schedulesv1' +# echo "$ENVIRONMENT_DATA" | jq -r '.schedulesv1alpha1' +# echo "$ENVIRONMENT_DATA" | jq -r '.prebackuppodsv1' +# echo "$ENVIRONMENT_DATA" | jq -r '.prebackuppodsv1alpha1' +# echo "$ENVIRONMENT_DATA" | jq -r '.mariadbconsumers' +# echo "$ENVIRONMENT_DATA" | jq -r '.mongodbconsumers' +# echo "$ENVIRONMENT_DATA" | jq -r '.postgresqlconsumers' + +if [ "$(featureFlag VARIABLES_ONLY)" = enabled ] +then + # update lagoon-env + # then patch any deployments with the new lagoon-env sha and force the pods to rollout + # this would make this easier https://github.com/uselagoon/build-deploy-tool/pull/397 + echo "no" +fi + +currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" +patchBuildStep "${buildStartTime}" "${buildStartTime}" "${currentStepEnd}" "${NAMESPACE}" "collectEnvironment" "Initial Environment Collection" "false" +previousStepEnd=${currentStepEnd} beginBuildStep "Initial Environment Setup" "initialSetup" echo "STEP: Preparation started ${buildStartTime}"