From e0c1da72385354f90fed80bb78ca49c6904cef65 Mon Sep 17 00:00:00 2001 From: wtschreiter Date: Wed, 26 Jun 2019 21:09:37 +0200 Subject: [PATCH] [FEATURE] global, cluster and project catalogs as code (#39 #44) * Add Descriptor for Rancher with Catalog client * Add Descriptor for Cluster with Catalog client * Add Descriptor for Project with Catalog client * Add catalog samples --- cmd/apply/apply.go | 3 +- cmd/show/show.go | 2 +- docs/cluster_descriptor.md | 38 +++ docs/index.md | 2 + docs/rancher_descriptor.md | 0 internal/pkg/ctl/cattle.go | 165 +++++++++-- internal/pkg/rancher/client/app_client.go | 2 +- .../pkg/rancher/client/app_client_test.go | 21 +- .../pkg/rancher/client/certificate_client.go | 2 +- .../rancher/client/certificate_client_test.go | 2 +- internal/pkg/rancher/client/clients.go | 20 +- .../rancher/client/cluster_catalog_client.go | 172 +++++++++++ .../client/cluster_catalog_client_test.go | 263 +++++++++++++++++ internal/pkg/rancher/client/cluster_client.go | 42 ++- .../pkg/rancher/client/cluster_client_test.go | 1 + .../pkg/rancher/client/config_map_client.go | 2 +- .../rancher/client/config_map_client_test.go | 2 +- internal/pkg/rancher/client/cronjob_client.go | 2 +- .../pkg/rancher/client/cronjob_client_test.go | 2 +- .../pkg/rancher/client/daemon_set_client.go | 2 +- .../rancher/client/daemon_set_client_test.go | 2 +- internal/pkg/rancher/client/deployment.go | 2 +- .../pkg/rancher/client/deployment_test.go | 2 +- .../client/docker_credential_client.go | 2 +- .../client/docker_credential_client_test.go | 2 +- internal/pkg/rancher/client/job_client.go | 2 +- .../pkg/rancher/client/job_client_test.go | 2 +- .../pkg/rancher/client/namespace_client.go | 2 +- .../rancher/client/namespace_client_test.go | 2 +- .../client/persistent_volume_client.go | 2 +- .../client/persistent_volume_client_test.go | 2 +- .../rancher/client/project_catalog_client.go | 172 +++++++++++ .../client/project_catalog_client_test.go | 269 ++++++++++++++++++ internal/pkg/rancher/client/project_client.go | 55 +++- .../pkg/rancher/client/project_client_test.go | 3 +- .../rancher/client/rancher_catalog_client.go | 158 ++++++++++ .../client/rancher_catalog_client_test.go | 258 +++++++++++++++++ internal/pkg/rancher/client/rancher_client.go | 36 +++ .../pkg/rancher/client/rancher_client_test.go | 106 +++++++ .../pkg/rancher/client/resource_client.go | 22 ++ internal/pkg/rancher/client/secret_client.go | 2 +- .../pkg/rancher/client/secret_client_test.go | 2 +- .../pkg/rancher/client/stateful_set_client.go | 2 +- .../client/stateful_set_client_test.go | 2 +- .../rancher/client/storage_class_client.go | 2 +- .../client/storage_class_client_test.go | 2 +- .../pkg/rancher/cluster/cluster_converger.go | 44 +++ .../pkg/rancher/cluster/cluster_parser.go | 29 ++ internal/pkg/rancher/cluster/model/cluster.go | 37 +++ .../{ => cluster}/project/converger_test.go | 0 .../project/cronjob_converger.go | 2 +- .../project/cronjob_converger_test.go | 0 .../{ => cluster}/project/cronjob_parser.go | 4 +- .../project/daemonset_converger.go | 2 +- .../project/daemonset_converger_test.go | 0 .../{ => cluster}/project/daemonset_parser.go | 4 +- .../project/deployment_converger.go | 2 +- .../project/deployment_converger_test.go | 0 .../project/deployment_parser.go | 4 +- .../{ => cluster}/project/job_converger.go | 2 +- .../project/job_converger_test.go | 0 .../{ => cluster}/project/job_parser.go | 4 +- .../rancher/{ => cluster}/project/merge.go | 2 +- .../{ => cluster}/project/merge_test.go | 2 +- .../{ => cluster}/project/model/model.go | 47 +-- .../golden-files/descriptor.cron_job.golden | 0 .../golden-files/descriptor.daemonSet.golden | 0 .../golden-files/descriptor.deployment.golden | 0 .../golden-files/descriptor.job.golden | 0 .../descriptor.statefulSet.golden | 0 .../golden-files/simple-include.golden | 0 .../model/testdata/input/cron_job.yaml | 0 .../model/testdata/input/daemonSet.yaml | 0 .../model/testdata/input/deployment.yaml | 0 .../project/model/testdata/input/job.yaml | 0 .../model/testdata/input/statefulSet.yaml | 0 .../testdata/model/workload/cron_job.model | 0 .../testdata/model/workload/daemon_set.model | 0 .../testdata/model/workload/deployment.model | 0 .../testdata/model/workload/deployment.yaml | 0 .../model/testdata/model/workload/job.model | 0 .../model/testdata/model/workload/job.yaml | 0 .../model/workload/stateful_set.model | 0 .../testdata/model/workload/workload.model | 0 .../{ => cluster}/project/model/util.go | 0 .../project/model/workload_daemonset.go | 0 .../project/model/workload_daemonset_test.go | 0 .../project/model/workload_deployment.go | 0 .../project/model/workload_deployment_test.go | 0 .../project/model/workload_model.go | 0 .../project/model/workload_model_cron_job.go | 0 .../model/workload_model_cron_job_test.go | 0 .../project/model/workload_model_job.go | 0 .../project/model/workload_model_job_test.go | 0 .../project/model/workload_model_test.go | 0 .../project/model/workload_statefulset.go | 0 .../model/workload_statefulset_test.go | 0 .../rancher/{ => cluster}/project/parser.go | 2 +- .../{ => cluster}/project/parser_test.go | 2 +- .../project/project_converger.go | 12 +- .../project/project_converger_test.go | 0 .../project/statefulset_converger.go | 2 +- .../project/statefulset_converger_test.go | 0 .../project/statefulset_parser.go | 4 +- .../project/testdata/cycle-include/child.yaml | 0 .../testdata/cycle-include/project.yaml | 0 .../child-directory/child.1.yaml | 0 .../child-directory/child.2.yaml | 0 .../testdata/directory-include/project.yaml | 0 .../testdata/files-include/child.1.yaml | 0 .../testdata/files-include/child.2.yaml | 0 .../testdata/files-include/project.yaml | 0 .../golden-files/cycle-include.golden | 0 .../golden-files/directory-include.golden | 0 .../golden-files/files-include.golden | 0 .../golden-files/simple-include.golden | 0 .../golden-files/valid-project.golden | 0 .../testdata/include/simple/child.yaml | 0 .../testdata/include/simple/expected.yaml | 0 .../testdata/include/simple/parent.yaml | 0 .../project/testdata/input/cluster.yaml | 0 .../project/testdata/input/missing-kind.yaml | 0 .../testdata/projects/all-resources.yaml | 0 .../testdata/simple-include/child.yaml | 0 .../testdata/simple-include/project.yaml | 0 .../testdata/valid-project/license.file | 0 .../testdata/valid-project/project.yaml | 0 .../testdata/valid-project/values.yaml | 0 internal/pkg/rancher/model/rancher.go | 52 ++++ internal/pkg/rancher/rancher_converger.go | 44 +++ internal/pkg/rancher/rancher_parser.go | 29 ++ .../stubs/cluster_catalog_operations_stub.go | 115 ++++++++ .../stubs/project_catalog_operations_stub.go | 115 ++++++++ .../stubs/rancher_catalog_operations_stub.go | 115 ++++++++ sample/cluster-with-catalog/cluster.yaml | 7 + sample/cluster-with-catalog/values1.yaml | 2 + sample/cluster-with-catalog/values2.yaml | 2 + sample/project-with-catalog/project.yaml | 9 + sample/project-with-catalog/values1.yaml | 2 + sample/project-with-catalog/values2.yaml | 2 + sample/rancher-with-catalog/rancher.yaml | 7 + sample/rancher-with-catalog/values1.yaml | 2 + sample/rancher-with-catalog/values2.yaml | 2 + 143 files changed, 2449 insertions(+), 121 deletions(-) create mode 100644 docs/cluster_descriptor.md create mode 100644 docs/rancher_descriptor.md create mode 100644 internal/pkg/rancher/client/cluster_catalog_client.go create mode 100644 internal/pkg/rancher/client/cluster_catalog_client_test.go create mode 100644 internal/pkg/rancher/client/project_catalog_client.go create mode 100644 internal/pkg/rancher/client/project_catalog_client_test.go create mode 100644 internal/pkg/rancher/client/rancher_catalog_client.go create mode 100644 internal/pkg/rancher/client/rancher_catalog_client_test.go create mode 100644 internal/pkg/rancher/cluster/cluster_converger.go create mode 100644 internal/pkg/rancher/cluster/cluster_parser.go create mode 100644 internal/pkg/rancher/cluster/model/cluster.go rename internal/pkg/rancher/{ => cluster}/project/converger_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/cronjob_converger.go (98%) rename internal/pkg/rancher/{ => cluster}/project/cronjob_converger_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/cronjob_parser.go (87%) rename internal/pkg/rancher/{ => cluster}/project/daemonset_converger.go (98%) rename internal/pkg/rancher/{ => cluster}/project/daemonset_converger_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/daemonset_parser.go (87%) rename internal/pkg/rancher/{ => cluster}/project/deployment_converger.go (98%) rename internal/pkg/rancher/{ => cluster}/project/deployment_converger_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/deployment_parser.go (87%) rename internal/pkg/rancher/{ => cluster}/project/job_converger.go (98%) rename internal/pkg/rancher/{ => cluster}/project/job_converger_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/job_parser.go (87%) rename internal/pkg/rancher/{ => cluster}/project/merge.go (99%) rename internal/pkg/rancher/{ => cluster}/project/merge_test.go (98%) rename internal/pkg/rancher/{ => cluster}/project/model/model.go (75%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/golden-files/descriptor.cron_job.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/golden-files/descriptor.daemonSet.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/golden-files/descriptor.deployment.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/golden-files/descriptor.job.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/golden-files/descriptor.statefulSet.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/golden-files/simple-include.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/input/cron_job.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/input/daemonSet.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/input/deployment.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/input/job.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/input/statefulSet.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/cron_job.model (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/daemon_set.model (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/deployment.model (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/deployment.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/job.model (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/job.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/stateful_set.model (100%) rename internal/pkg/rancher/{ => cluster}/project/model/testdata/model/workload/workload.model (100%) rename internal/pkg/rancher/{ => cluster}/project/model/util.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_daemonset.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_daemonset_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_deployment.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_deployment_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_model.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_model_cron_job.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_model_cron_job_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_model_job.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_model_job_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_model_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_statefulset.go (100%) rename internal/pkg/rancher/{ => cluster}/project/model/workload_statefulset_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/parser.go (99%) rename internal/pkg/rancher/{ => cluster}/project/parser_test.go (98%) rename internal/pkg/rancher/{ => cluster}/project/project_converger.go (92%) rename internal/pkg/rancher/{ => cluster}/project/project_converger_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/statefulset_converger.go (98%) rename internal/pkg/rancher/{ => cluster}/project/statefulset_converger_test.go (100%) rename internal/pkg/rancher/{ => cluster}/project/statefulset_parser.go (87%) rename internal/pkg/rancher/{ => cluster}/project/testdata/cycle-include/child.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/cycle-include/project.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/directory-include/child-directory/child.1.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/directory-include/child-directory/child.2.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/directory-include/project.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/files-include/child.1.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/files-include/child.2.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/files-include/project.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/golden-files/cycle-include.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/golden-files/directory-include.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/golden-files/files-include.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/golden-files/simple-include.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/golden-files/valid-project.golden (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/include/simple/child.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/include/simple/expected.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/include/simple/parent.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/input/cluster.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/input/missing-kind.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/projects/all-resources.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/simple-include/child.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/simple-include/project.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/valid-project/license.file (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/valid-project/project.yaml (100%) rename internal/pkg/rancher/{ => cluster}/project/testdata/valid-project/values.yaml (100%) create mode 100644 internal/pkg/rancher/model/rancher.go create mode 100644 internal/pkg/rancher/rancher_converger.go create mode 100644 internal/pkg/rancher/rancher_parser.go create mode 100644 internal/pkg/rancher/stubs/cluster_catalog_operations_stub.go create mode 100644 internal/pkg/rancher/stubs/project_catalog_operations_stub.go create mode 100644 internal/pkg/rancher/stubs/rancher_catalog_operations_stub.go create mode 100644 sample/cluster-with-catalog/cluster.yaml create mode 100644 sample/cluster-with-catalog/values1.yaml create mode 100644 sample/cluster-with-catalog/values2.yaml create mode 100644 sample/project-with-catalog/project.yaml create mode 100644 sample/project-with-catalog/values1.yaml create mode 100644 sample/project-with-catalog/values2.yaml create mode 100644 sample/rancher-with-catalog/rancher.yaml create mode 100644 sample/rancher-with-catalog/values1.yaml create mode 100644 sample/rancher-with-catalog/values2.yaml diff --git a/cmd/apply/apply.go b/cmd/apply/apply.go index 36d3c78..3bb6eb5 100644 --- a/cmd/apply/apply.go +++ b/cmd/apply/apply.go @@ -21,7 +21,7 @@ import ( "github.com/bitgrip/cattlectl/cmd/utils" "github.com/bitgrip/cattlectl/internal/pkg/config" "github.com/bitgrip/cattlectl/internal/pkg/ctl" - "github.com/bitgrip/cattlectl/internal/pkg/rancher/project" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project" "github.com/bitgrip/cattlectl/internal/pkg/template" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -48,6 +48,7 @@ var ( newProjectParser = project.NewProjectParser ) +// BaseCommand is accessor to the package base command func BaseCommand(config config.Config, init func()) *cobra.Command { rootConfig = config initCommand = init diff --git a/cmd/show/show.go b/cmd/show/show.go index 32ff83b..e4fce4f 100644 --- a/cmd/show/show.go +++ b/cmd/show/show.go @@ -22,7 +22,7 @@ import ( "github.com/bitgrip/cattlectl/cmd/utils" "github.com/bitgrip/cattlectl/internal/pkg/config" "github.com/bitgrip/cattlectl/internal/pkg/ctl" - "github.com/bitgrip/cattlectl/internal/pkg/rancher/project" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project" "github.com/bitgrip/cattlectl/internal/pkg/template" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/docs/cluster_descriptor.md b/docs/cluster_descriptor.md new file mode 100644 index 0000000..d435c84 --- /dev/null +++ b/docs/cluster_descriptor.md @@ -0,0 +1,38 @@ +Cluster Descriptor data model +============================= + +ClusterDescriptor Structur: +--------------------------- + +### Toplevel ClusterDescriptor + +| Field | Description | +|-----------------|-----------------------------------------------------------------------| +| __api_version__ | The __\.\__ version used for this descriptor. | +| __kind__ | The kind of descriptor in this file (`Project`) | +| __metadata__ | Metainformation about this descriptor e.g.: name and cluster_name | +| __catalogs__ | List of namespaces to be part of this project | + +### metadata + +* In the descriptor only `name` should be set. +* All other fields are read from configuration or rancher + +| Field | Description | +|------------------|------------------------------------------------------------------------------------------| +| __name__ | The name of the cluster **Optional or placed from cattleclt configuration** | +| __id__ | Rancher internal ID of this project (**read from rancher**) | +| __rancher_url__ | The URL to reach the rancher (**placed from cattleclt configuration**) | +| __access_key__ | The access key to access rancher with (**placed from cattleclt configuration**) | +| __secret_key__ | The secret key to access rancher with (**placed from cattleclt configuration**) | +| __token_key__ | The token key to access rancher with (**placed from cattleclt configuration**) | + +#### catalogs + +| Field | Description | +|--------------|-----------------------------| +| __name__ | The name of the catalog | +| __url__ | The URL of the catalog | +| __branch__ | The branch of the catalog | +| __username__ | The username of the catalog | +| __password__ | The password of the catalog | \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index e651614..c930303 100644 --- a/docs/index.md +++ b/docs/index.md @@ -82,5 +82,7 @@ Finding more informations ------------------------- * [Descriptor templates](descriptor_templates.md) +* [RancherDescriptor data model](rancher_descriptor.md) +* [ClusterDescriptor data model](cluster_descriptor.md) * [ProjectDescriptor data model](project_descriptor.md) * [cattlectl CLI documentation](cattlectl.md) diff --git a/docs/rancher_descriptor.md b/docs/rancher_descriptor.md new file mode 100644 index 0000000..e69de29 diff --git a/internal/pkg/ctl/cattle.go b/internal/pkg/ctl/cattle.go index 829539b..5e4dc30 100644 --- a/internal/pkg/ctl/cattle.go +++ b/internal/pkg/ctl/cattle.go @@ -18,25 +18,21 @@ import ( "fmt" "github.com/bitgrip/cattlectl/internal/pkg/config" + rancher "github.com/bitgrip/cattlectl/internal/pkg/rancher" rancher_client "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" - "github.com/bitgrip/cattlectl/internal/pkg/rancher/project" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + cluster "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster" + clusterModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/model" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" yaml "gopkg.in/yaml.v2" ) -// Supported descriptor expected in the field 'kind' -const ( - ProjectKind = "Project" - JobKind = "Job" - CronJobKind = "CronJob" - DeploymentKind = "Deployment" - DaemonSetKind = "DaemonSet" - StatefulSetKind = "StatefulSet" -) - var ( newRancherClient = rancher_client.NewRancherClient + newRancherConverger = rancher.NewRancherConverger + newClusterConverger = cluster.NewClusterConverger newProjectConverger = project.NewProjectConverger newJobConverger = project.NewJobConverger newCronJobConverger = project.NewCronJobConverger @@ -44,6 +40,8 @@ var ( newDaemonSetConverger = project.NewDaemonSetConverger newStatefulSetConverger = project.NewStatefulSetConverger + newRancherParser = rancher.NewRancherParser + newClusterParser = cluster.NewClusterParser newProjectParser = project.NewProjectParser newJobParser = project.NewJobParser newCronJobParser = project.NewCronJobParser @@ -62,7 +60,23 @@ func ApplyDescriptor(file string, data []byte, values map[string]interface{}, co return fmt.Errorf("Unsupported api version %s", apiVersion) } switch kind { - case ProjectKind: + case rancherModel.RancherKind: + descriptor := rancherModel.Rancher{} + if err := newRancherParser(file, values).Parse(data, &descriptor); err != nil { + return err + } + if err := ApplyRancher(descriptor, config); err != nil { + return err + } + case rancherModel.ClusterKind: + descriptor := clusterModel.Cluster{} + if err := newClusterParser(file, values).Parse(data, &descriptor); err != nil { + return err + } + if err := ApplyCluster(descriptor, config); err != nil { + return err + } + case rancherModel.ProjectKind: project := projectModel.Project{} if err := newProjectParser(file, values).Parse(data, &project); err != nil { return err @@ -70,7 +84,7 @@ func ApplyDescriptor(file string, data []byte, values map[string]interface{}, co if err := ApplyProject(project, config); err != nil { return err } - case JobKind: + case rancherModel.JobKind: jobDescriptor := projectModel.JobDescriptor{} if err := newJobParser(file, values).Parse(data, &jobDescriptor); err != nil { return err @@ -78,7 +92,7 @@ func ApplyDescriptor(file string, data []byte, values map[string]interface{}, co if err := ApplyJob(jobDescriptor, config); err != nil { return err } - case CronJobKind: + case rancherModel.CronJobKind: cronJobDescriptor := projectModel.CronJobDescriptor{} if err := newCronJobParser(file, values).Parse(data, &cronJobDescriptor); err != nil { return err @@ -86,7 +100,7 @@ func ApplyDescriptor(file string, data []byte, values map[string]interface{}, co if err := ApplyCronJob(cronJobDescriptor, config); err != nil { return err } - case DeploymentKind: + case rancherModel.DeploymentKind: deploymentDescriptor := projectModel.DeploymentDescriptor{} if err := newDeploymentParser(file, values).Parse(data, &deploymentDescriptor); err != nil { return err @@ -94,7 +108,7 @@ func ApplyDescriptor(file string, data []byte, values map[string]interface{}, co if err := ApplyDeployment(deploymentDescriptor, config); err != nil { return err } - case DaemonSetKind: + case rancherModel.DaemonSetKind: daemonSetDescriptor := projectModel.DaemonSetDescriptor{} if err := newDaemonSetParser(file, values).Parse(data, &daemonSetDescriptor); err != nil { return err @@ -102,7 +116,7 @@ func ApplyDescriptor(file string, data []byte, values map[string]interface{}, co if err := ApplyDaemonSet(daemonSetDescriptor, config); err != nil { return err } - case StatefulSetKind: + case rancherModel.StatefulSetKind: statefulSetDescriptor := projectModel.StatefulSetDescriptor{} if err := newStatefulSetParser(file, values).Parse(data, &statefulSetDescriptor); err != nil { return err @@ -194,6 +208,32 @@ func ApplyProject(project projectModel.Project, config config.Config) error { return converger.Converge() } +// ApplyCluster the the CTL perform a apply action to a cluster descriptor +func ApplyCluster(cluster clusterModel.Cluster, config config.Config) error { + rancherClient, err := fillClusterMetadata(&cluster.Metadata, config) + if err != nil { + return err + } + converger, err := newClusterConverger(cluster, rancherClient) + if err != nil { + return err + } + return converger.Converge() +} + +// ApplyRancher the the CTL perform a apply action to a cluster descriptor +func ApplyRancher(rancher rancherModel.Rancher, config config.Config) error { + rancherConfig, err := fillRancherMetadata(&rancher.Metadata, config) + if err != nil { + return err + } + converger, err := newRancherConverger(rancher, rancherConfig) + if err != nil { + return err + } + return converger.Converge() +} + // GetAPIVersionAndKind reads API version and kind from the data func GetAPIVersionAndKind(data []byte) (string, string, error) { structure := make(map[string]interface{}) @@ -227,24 +267,51 @@ func ParseAndPrintDescriptor(file string, data []byte, values map[string]interfa } var descriptor interface{} switch kind { - case ProjectKind: + case rancherModel.RancherKind: + descriptor = rancherModel.Rancher{} + if err = newRancherParser(file, values).Parse(data, &descriptor); err != nil { + return err + } + case rancherModel.ClusterKind: + descriptor = clusterModel.Cluster{} + if err = newRancherParser(file, values).Parse(data, &descriptor); err != nil { + return err + } + case rancherModel.ProjectKind: project := projectModel.Project{} if err = newProjectParser(file, values).Parse(data, &project); err != nil { return err } descriptor = project - case JobKind: + case rancherModel.JobKind: jobDescriptor := projectModel.JobDescriptor{} if err = newJobParser(file, values).Parse(data, &jobDescriptor); err != nil { return err } descriptor = jobDescriptor - case CronJobKind: + case rancherModel.CronJobKind: cronJobDescriptor := projectModel.CronJobDescriptor{} if err = newCronJobParser(file, values).Parse(data, &cronJobDescriptor); err != nil { return err } descriptor = cronJobDescriptor + case rancherModel.DeploymentKind: + descriptor = projectModel.Deployment{} + if err = newDeploymentParser(file, values).Parse(data, &descriptor); err != nil { + return err + } + case rancherModel.StatefulSetKind: + descriptor = projectModel.StatefulSet{} + if err = newStatefulSetParser(file, values).Parse(data, &descriptor); err != nil { + return err + } + case rancherModel.DaemonSetKind: + descriptor = projectModel.DaemonSet{} + if err = newDaemonSetParser(file, values).Parse(data, &descriptor); err != nil { + return err + } + default: + return fmt.Errorf("Unknown descriptor %s", kind) } out, err := yaml.Marshal(descriptor) if err != nil { @@ -333,3 +400,59 @@ func fillProjectMetadata(metadata *projectModel.ProjectMetadata, config config.C } return rancherClient, clusterClient, nil } + +func fillClusterMetadata(metadata *clusterModel.ClusterMetadata, config config.Config) (rancher_client.RancherClient, error) { + if config.RancherURL() != "" { + metadata.RancherURL = config.RancherURL() + } + if config.AccessKey() != "" { + metadata.AccessKey = config.AccessKey() + } + if config.SecretKey() != "" { + metadata.SecretKey = config.SecretKey() + } + if config.TokenKey() != "" { + metadata.TokenKey = config.TokenKey() + } + if config.ClusterName() != "" { + metadata.Name = config.ClusterName() + } + if config.ClusterID() != "" { + metadata.ID = config.ClusterID() + } + + rancherClient, err := newRancherClient(rancher_client.RancherConfig{ + RancherURL: metadata.RancherURL, + AccessKey: metadata.AccessKey, + SecretKey: metadata.SecretKey, + Insecure: config.InsecureAPI(), + CACerts: config.CACerts(), + }) + if err != nil { + return nil, err + } + return rancherClient, nil +} + +func fillRancherMetadata(metadata *rancherModel.RancherMetadata, config config.Config) (rancher_client.RancherConfig, error) { + if config.RancherURL() != "" { + metadata.RancherURL = config.RancherURL() + } + if config.AccessKey() != "" { + metadata.AccessKey = config.AccessKey() + } + if config.SecretKey() != "" { + metadata.SecretKey = config.SecretKey() + } + if config.TokenKey() != "" { + metadata.TokenKey = config.TokenKey() + } + + return rancher_client.RancherConfig{ + RancherURL: metadata.RancherURL, + AccessKey: metadata.AccessKey, + SecretKey: metadata.SecretKey, + Insecure: config.InsecureAPI(), + CACerts: config.CACerts(), + }, nil +} diff --git a/internal/pkg/rancher/client/app_client.go b/internal/pkg/rancher/client/app_client.go index e7f1d80..2bb1ff0 100644 --- a/internal/pkg/rancher/client/app_client.go +++ b/internal/pkg/rancher/client/app_client.go @@ -19,7 +19,7 @@ import ( "reflect" "strings" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/app_client_test.go b/internal/pkg/rancher/client/app_client_test.go index 5f9865e..152b10b 100644 --- a/internal/pkg/rancher/client/app_client_test.go +++ b/internal/pkg/rancher/client/app_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" @@ -29,7 +29,6 @@ import ( const ( simpleAppName = "simple-app" - simpleCatalog = "simple-catalog" ) func Test_appClient_Exists(t *testing.T) { @@ -46,7 +45,7 @@ func Test_appClient_Exists(t *testing.T) { t, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, "1.1.1", map[string]string{}, map[string]string{}, @@ -64,7 +63,7 @@ func Test_appClient_Exists(t *testing.T) { simpleProjectID, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, globalCatalogType, "1.1.1", map[string]string{}, @@ -102,7 +101,7 @@ func Test_appClient_Create(t *testing.T) { simpleProjectID, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, globalCatalogType, "1.1.1", map[string]string{}, @@ -118,7 +117,7 @@ func Test_appClient_Create(t *testing.T) { simpleProjectID, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, clusterCatalogType, "1.1.1", map[string]string{}, @@ -134,7 +133,7 @@ func Test_appClient_Create(t *testing.T) { simpleProjectID, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, projectCatalogType, "1.1.1", map[string]string{}, @@ -168,7 +167,7 @@ func Test_appClient_Upgrade(t *testing.T) { t, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, "1.1.1", map[string]string{ "key": "value", @@ -187,7 +186,7 @@ func Test_appClient_Upgrade(t *testing.T) { t, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, "1.1.1", map[string]string{ "key": "value", @@ -206,7 +205,7 @@ func Test_appClient_Upgrade(t *testing.T) { t, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, "1.1.1", nil, nil, @@ -225,7 +224,7 @@ key: changed-value t, simpleAppName, simpleNamespaceName, - simpleCatalog, + simpleCatalogName, "1.1.1", nil, nil, diff --git a/internal/pkg/rancher/client/certificate_client.go b/internal/pkg/rancher/client/certificate_client.go index 6977da4..414bfba 100644 --- a/internal/pkg/rancher/client/certificate_client.go +++ b/internal/pkg/rancher/client/certificate_client.go @@ -18,7 +18,7 @@ import ( "fmt" "strings" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/certificate_client_test.go b/internal/pkg/rancher/client/certificate_client_test.go index 2b01376..da27960 100644 --- a/internal/pkg/rancher/client/certificate_client_test.go +++ b/internal/pkg/rancher/client/certificate_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/clients.go b/internal/pkg/rancher/client/clients.go index 8afa412..b91b429 100644 --- a/internal/pkg/rancher/client/clients.go +++ b/internal/pkg/rancher/client/clients.go @@ -15,7 +15,8 @@ package client import ( - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" backendClusterClient "github.com/rancher/types/client/cluster/v3" backendRancherClient "github.com/rancher/types/client/management/v3" backendProjectClient "github.com/rancher/types/client/project/v3" @@ -25,6 +26,8 @@ import ( type RancherClient interface { Cluster(clusterName string) (ClusterClient, error) Clusters() ([]ClusterClient, error) + Catalog(string) (CatalogClient, error) + Catalogs() ([]CatalogClient, error) backendRancherClient() (*backendRancherClient.Client, error) } @@ -56,6 +59,8 @@ type ClusterClient interface { PersistentVolumes() ([]PersistentVolumeClient, error) Namespace(name, projectName string) (NamespaceClient, error) Namespaces(projectName string) ([]NamespaceClient, error) + Catalog(string) (CatalogClient, error) + Catalogs() ([]CatalogClient, error) backendRancherClient() (*backendRancherClient.Client, error) backendClusterClient() (*backendClusterClient.Client, error) @@ -93,17 +98,28 @@ type ProjectClient interface { DaemonSets(namespaceName string) ([]DaemonSetClient, error) StatefulSet(name, namespaceName string) (StatefulSetClient, error) StatefulSets(namespaceName string) ([]StatefulSetClient, error) + Catalog(string) (CatalogClient, error) + Catalogs() ([]CatalogClient, error) + backendRancherClient() (*backendRancherClient.Client, error) + backendClusterClient() (*backendClusterClient.Client, error) backendProjectClient() (*backendProjectClient.Client, error) config() RancherConfig } +// CatalogClient interacts with a Rancher catalog resource +type CatalogClient interface { + ResourceClient + Data() (rancherModel.Catalog, error) + SetData(catalog rancherModel.Catalog) error +} + // NamespaceClient interacts with a Rancher namespace resource type NamespaceClient interface { ResourceClient HasProject() (bool, error) Data() (projectModel.Namespace, error) - SetData(storageClass projectModel.Namespace) error + SetData(namespace projectModel.Namespace) error } // StorageClassClient interacts with a Rancher storage class resource diff --git a/internal/pkg/rancher/client/cluster_catalog_client.go b/internal/pkg/rancher/client/cluster_catalog_client.go new file mode 100644 index 0000000..f82d0ff --- /dev/null +++ b/internal/pkg/rancher/client/cluster_catalog_client.go @@ -0,0 +1,172 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by cataloglicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "fmt" + + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/rancher/norman/types" + backendRancherClient "github.com/rancher/types/client/management/v3" + "github.com/sirupsen/logrus" +) + +func newClusterCatalogClientWithData( + catalog rancherModel.Catalog, + clusterClient ClusterClient, + logger *logrus.Entry, +) (CatalogClient, error) { + result, err := newClusterCatalogClient( + catalog.Name, + clusterClient, + logger, + ) + if err != nil { + return nil, err + } + err = result.SetData(catalog) + return result, err +} + +func newClusterCatalogClient( + name string, + clusterClient ClusterClient, + logger *logrus.Entry, +) (CatalogClient, error) { + return &clusterCatalogClient{ + resourceClient: resourceClient{ + name: name, + logger: logger.WithField("catalog_name", name), + }, + clusterClient: clusterClient, + }, nil +} + +type clusterCatalogClient struct { + resourceClient + catalog rancherModel.Catalog + clusterClient ClusterClient +} + +func (client *clusterCatalogClient) Exists() (bool, error) { + backendClient, err := client.clusterClient.backendRancherClient() + if err != nil { + return false, err + } + clusterID, err := client.clusterClient.ID() + if err != nil { + return false, err + } + collection, err := backendClient.ClusterCatalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "name": client.name, + "clusterId": clusterID, + }, + }) + if nil != err { + client.logger.WithError(err).Error("Failed to read catalog list") + return false, fmt.Errorf("Failed to read catalog list, %v", err) + } + for _, item := range collection.Data { + if item.Name == client.name { + return true, nil + } + } + client.logger.Debug("Catalog not found") + return false, nil +} + +func (client *clusterCatalogClient) Create() error { + backendClient, err := client.clusterClient.backendRancherClient() + if err != nil { + return err + } + clusterID, err := client.clusterClient.ID() + if err != nil { + return err + } + client.logger.Info("Create new catalog") + _, err = backendClient.ClusterCatalog.Create(&backendRancherClient.ClusterCatalog{ + Name: client.catalog.Name, + ClusterID: clusterID, + URL: client.catalog.URL, + Branch: client.catalog.Branch, + Username: client.catalog.Username, + Password: client.catalog.Password, + Labels: map[string]string{ + "cattlectl.io/hash": hashOf(client.catalog), + }, + }) + return err +} + +func (client *clusterCatalogClient) Upgrade() error { + backendClient, err := client.clusterClient.backendRancherClient() + if err != nil { + return err + } + clusterID, err := client.clusterClient.ID() + if err != nil { + return err + } + client.logger.Trace("Load from rancher") + collection, err := backendClient.ClusterCatalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "name": client.name, + "clusterId": clusterID, + }, + }) + if nil != err { + client.logger.WithError(err).Error("Failed to read catalog list") + return fmt.Errorf("Failed to read catalog list, %v", err) + } + + if len(collection.Data) == 0 { + return fmt.Errorf("Catalog %v not found", client.name) + } + + existingCatalog := collection.Data[0] + if isClusterCatalogUnchanged(existingCatalog, client.catalog) { + client.logger.Debug("Skip upgrade catalog - no changes") + return nil + } + client.logger.Info("Upgrade ClusterCatalog") + existingCatalog.Labels["cattlectl.io/hash"] = hashOf(client.catalog) + existingCatalog.URL = client.catalog.URL + existingCatalog.Branch = client.catalog.Branch + existingCatalog.Username = client.catalog.Username + existingCatalog.Password = client.catalog.Password + + _, err = backendClient.ClusterCatalog.Replace(&existingCatalog) + return err +} + +func (client *clusterCatalogClient) Data() (rancherModel.Catalog, error) { + return client.catalog, nil +} + +func (client *clusterCatalogClient) SetData(catalog rancherModel.Catalog) error { + client.name = catalog.Name + client.catalog = catalog + return nil +} + +func isClusterCatalogUnchanged(existingCatalog backendRancherClient.ClusterCatalog, catalog rancherModel.Catalog) bool { + hash, hashExists := existingCatalog.Labels["cattlectl.io/hash"] + if !hashExists { + return false + } + return hash == hashOf(catalog) +} diff --git a/internal/pkg/rancher/client/cluster_catalog_client_test.go b/internal/pkg/rancher/client/cluster_catalog_client_test.go new file mode 100644 index 0000000..a6d5d14 --- /dev/null +++ b/internal/pkg/rancher/client/cluster_catalog_client_test.go @@ -0,0 +1,263 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "fmt" + "reflect" + "testing" + + "github.com/bitgrip/cattlectl/internal/pkg/assert" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" + "github.com/rancher/norman/types" + backendRancherClient "github.com/rancher/types/client/management/v3" + "github.com/sirupsen/logrus" +) + +func Test_clusterCatalogClient_Exists(t *testing.T) { + tests := []struct { + name string + client *clusterCatalogClient + wanted bool + wantErr bool + wantedErr string + }{ + { + name: "Existing", + client: existingClusterCatalogClient( + t, + simpleCatalogName, + simpleClusterID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wanted: true, + wantErr: false, + }, + { + name: "Not_Existing", + client: notExistingClusterCatalogClient( + t, + simpleCatalogName, + simpleClusterID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wanted: false, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.client.Exists() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + assert.Equals(t, tt.wanted, got) + } + }) + } +} + +func Test_clusterCatalogClient_Create(t *testing.T) { + tests := []struct { + name string + client *clusterCatalogClient + wantErr bool + wantedErr string + }{ + { + name: "Create", + client: notExistingClusterCatalogClient( + t, + simpleCatalogName, + simpleClusterID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.client.Create() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + } + }) + } +} + +func Test_clusterCatalogClient_Upgrade(t *testing.T) { + tests := []struct { + name string + client *clusterCatalogClient + wantErr bool + wantedErr string + }{ + { + name: "Create", + client: existingClusterCatalogClient( + t, + simpleCatalogName, + simpleClusterID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.client.Upgrade() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + } + }) + } +} + +func existingClusterCatalogClient(t *testing.T, name, clusterID, url, branch, username, password string) *clusterCatalogClient { + testClients := stubs.CreateBackendStubs(t) + expectedListOpts := &types.ListOpts{ + Filters: map[string]interface{}{ + "name": name, + "clusterId": clusterID, + }, + } + clusterCatalogData := rancherModel.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + } + expectedBackendrCatalog := &backendRancherClient.ClusterCatalog{ + Name: name, + ClusterID: clusterID, + URL: url, + Branch: branch, + Username: username, + Password: password, + Labels: map[string]string{"cattlectl.io/hash": hashOf(clusterCatalogData)}, + } + + clusterCatalogOperationsStub := stubs.CreateClusterCatalogOperationsStub(t) + clusterCatalogOperationsStub.DoList = func(opts *types.ListOpts) (*backendRancherClient.ClusterCatalogCollection, error) { + if !reflect.DeepEqual(expectedListOpts, opts) { + return nil, fmt.Errorf("Unexpected ListOpts %v", opts) + } + return &backendRancherClient.ClusterCatalogCollection{ + Data: []backendRancherClient.ClusterCatalog{ + backendRancherClient.ClusterCatalog{ + Name: name, + ClusterID: clusterID, + Labels: map[string]string{}, + }, + }, + }, nil + } + clusterCatalogOperationsStub.DoReplace = func(existing *backendRancherClient.ClusterCatalog) (*backendRancherClient.ClusterCatalog, error) { + if !reflect.DeepEqual(expectedBackendrCatalog, existing) { + return nil, fmt.Errorf("Unexpected ClusterCatalog %v", existing) + } + return existing, nil + } + testClients.ManagementClient.ClusterCatalog = clusterCatalogOperationsStub + rancherClient := simpleRancherClient() + rancherClient._backendRancherClient = testClients.ManagementClient + clusterClient := simpleClusterClient() + clusterClient.rancherClient = rancherClient + result, err := newClusterCatalogClient( + name, + clusterClient, + logrus.New().WithFields(logrus.Fields{}), + ) + assert.Ok(t, err) + clusterCatalogClientResult := result.(*clusterCatalogClient) + clusterCatalogClientResult.catalog = clusterCatalogData + return clusterCatalogClientResult +} + +func notExistingClusterCatalogClient(t *testing.T, name, clusterID, url, branch, username, password string) *clusterCatalogClient { + testClients := stubs.CreateBackendStubs(t) + expectedListOpts := &types.ListOpts{ + Filters: map[string]interface{}{ + "name": name, + "clusterId": clusterID, + }, + } + clusterCatalogData := rancherModel.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + } + expectedBackendrCatalog := &backendRancherClient.ClusterCatalog{ + Name: name, + ClusterID: clusterID, + URL: url, + Branch: branch, + Username: username, + Password: password, + Labels: map[string]string{"cattlectl.io/hash": hashOf(clusterCatalogData)}, + } + + clusterCatalogOperationsStub := stubs.CreateClusterCatalogOperationsStub(t) + clusterCatalogOperationsStub.DoList = func(opts *types.ListOpts) (*backendRancherClient.ClusterCatalogCollection, error) { + if !reflect.DeepEqual(expectedListOpts, opts) { + return nil, fmt.Errorf("Unexpected ListOpts %v", opts) + } + return &backendRancherClient.ClusterCatalogCollection{ + Data: []backendRancherClient.ClusterCatalog{}, + }, nil + } + clusterCatalogOperationsStub.DoCreate = func(clusterCatalog *backendRancherClient.ClusterCatalog) (*backendRancherClient.ClusterCatalog, error) { + if !reflect.DeepEqual(expectedBackendrCatalog, clusterCatalog) { + return nil, fmt.Errorf("Unexpected Catalog\n%v\n%v", expectedBackendrCatalog, clusterCatalog) + } + + return clusterCatalog, nil + } + testClients.ManagementClient.ClusterCatalog = clusterCatalogOperationsStub + rancherClient := simpleRancherClient() + rancherClient._backendRancherClient = testClients.ManagementClient + clusterClient := simpleClusterClient() + clusterClient.rancherClient = rancherClient + result, err := newClusterCatalogClient( + name, + clusterClient, + logrus.New().WithFields(logrus.Fields{}), + ) + assert.Ok(t, err) + clusterCatalogClientResult := result.(*clusterCatalogClient) + clusterCatalogClientResult.catalog = clusterCatalogData + return clusterCatalogClientResult +} diff --git a/internal/pkg/rancher/client/cluster_client.go b/internal/pkg/rancher/client/cluster_client.go index c9f3e6a..c0ad1b3 100644 --- a/internal/pkg/rancher/client/cluster_client.go +++ b/internal/pkg/rancher/client/cluster_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + clusterModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/model" "github.com/rancher/norman/types" backendClusterClient "github.com/rancher/types/client/cluster/v3" backendRancherClient "github.com/rancher/types/client/management/v3" @@ -41,6 +41,7 @@ func newClusterClient( storageClasses: make(map[string]StorageClassClient), persistentVolumes: make(map[string]PersistentVolumeClient), namespaces: make(map[string]namespaceCacheEntry), + catalogClients: make(map[string]CatalogClient), }, nil } @@ -49,11 +50,12 @@ type clusterClient struct { config RancherConfig rancherClient RancherClient _backendClusterClient *backendClusterClient.Client - cluster projectModel.Cluster + cluster clusterModel.Cluster projectClients map[string]ProjectClient storageClasses map[string]StorageClassClient persistentVolumes map[string]PersistentVolumeClient namespaces map[string]namespaceCacheEntry + catalogClients map[string]CatalogClient } type namespaceCacheEntry struct { @@ -280,3 +282,39 @@ func (client *clusterClient) backendClusterClient() (*backendClusterClient.Clien } return client._backendClusterClient, nil } + +func (client *clusterClient) Catalog(catalogName string) (CatalogClient, error) { + if cache, exists := client.catalogClients[catalogName]; exists { + return cache, nil + } + result, err := newClusterCatalogClient(catalogName, client, client.logger) + if err != nil { + return nil, err + } + client.catalogClients[catalogName] = result + return result, nil +} + +func (client *clusterClient) Catalogs() ([]CatalogClient, error) { + backendRancherClient, err := client.backendRancherClient() + if err != nil { + return nil, err + } + collection, err := backendRancherClient.ClusterCatalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "clusterId": client.id, + }, + }) + if err != nil { + return nil, err + } + result := make([]CatalogClient, len(collection.Data)) + for i, backendCatalog := range collection.Data { + catalog, err := client.Catalog(backendCatalog.Name) + if err != nil { + return nil, err + } + result[i] = catalog + } + return result, nil +} diff --git a/internal/pkg/rancher/client/cluster_client_test.go b/internal/pkg/rancher/client/cluster_client_test.go index 8dc301a..d279f7d 100644 --- a/internal/pkg/rancher/client/cluster_client_test.go +++ b/internal/pkg/rancher/client/cluster_client_test.go @@ -401,6 +401,7 @@ func simpleClusterClient() *clusterClient { storageClasses: make(map[string]StorageClassClient), persistentVolumes: make(map[string]PersistentVolumeClient), namespaces: make(map[string]namespaceCacheEntry), + catalogClients: make(map[string]CatalogClient), } } diff --git a/internal/pkg/rancher/client/config_map_client.go b/internal/pkg/rancher/client/config_map_client.go index 9e625ad..4d4ca34 100644 --- a/internal/pkg/rancher/client/config_map_client.go +++ b/internal/pkg/rancher/client/config_map_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/config_map_client_test.go b/internal/pkg/rancher/client/config_map_client_test.go index 2c15476..434fc3c 100644 --- a/internal/pkg/rancher/client/config_map_client_test.go +++ b/internal/pkg/rancher/client/config_map_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/cronjob_client.go b/internal/pkg/rancher/client/cronjob_client.go index 27f94c7..0943d1d 100644 --- a/internal/pkg/rancher/client/cronjob_client.go +++ b/internal/pkg/rancher/client/cronjob_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" "github.com/sirupsen/logrus" ) diff --git a/internal/pkg/rancher/client/cronjob_client_test.go b/internal/pkg/rancher/client/cronjob_client_test.go index 56468b4..b267583 100644 --- a/internal/pkg/rancher/client/cronjob_client_test.go +++ b/internal/pkg/rancher/client/cronjob_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/daemon_set_client.go b/internal/pkg/rancher/client/daemon_set_client.go index b497778..60c3477 100644 --- a/internal/pkg/rancher/client/daemon_set_client.go +++ b/internal/pkg/rancher/client/daemon_set_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" "github.com/sirupsen/logrus" ) diff --git a/internal/pkg/rancher/client/daemon_set_client_test.go b/internal/pkg/rancher/client/daemon_set_client_test.go index 411de6a..51626b4 100644 --- a/internal/pkg/rancher/client/daemon_set_client_test.go +++ b/internal/pkg/rancher/client/daemon_set_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/deployment.go b/internal/pkg/rancher/client/deployment.go index 9dd5e39..08499d3 100644 --- a/internal/pkg/rancher/client/deployment.go +++ b/internal/pkg/rancher/client/deployment.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" "github.com/sirupsen/logrus" ) diff --git a/internal/pkg/rancher/client/deployment_test.go b/internal/pkg/rancher/client/deployment_test.go index cf54bf7..786c022 100644 --- a/internal/pkg/rancher/client/deployment_test.go +++ b/internal/pkg/rancher/client/deployment_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/docker_credential_client.go b/internal/pkg/rancher/client/docker_credential_client.go index 884645f..c353796 100644 --- a/internal/pkg/rancher/client/docker_credential_client.go +++ b/internal/pkg/rancher/client/docker_credential_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/docker_credential_client_test.go b/internal/pkg/rancher/client/docker_credential_client_test.go index 5d618c6..737208e 100644 --- a/internal/pkg/rancher/client/docker_credential_client_test.go +++ b/internal/pkg/rancher/client/docker_credential_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/job_client.go b/internal/pkg/rancher/client/job_client.go index 14d681a..0abc5bd 100644 --- a/internal/pkg/rancher/client/job_client.go +++ b/internal/pkg/rancher/client/job_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" "github.com/sirupsen/logrus" ) diff --git a/internal/pkg/rancher/client/job_client_test.go b/internal/pkg/rancher/client/job_client_test.go index e6c4b0e..4558adf 100644 --- a/internal/pkg/rancher/client/job_client_test.go +++ b/internal/pkg/rancher/client/job_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/namespace_client.go b/internal/pkg/rancher/client/namespace_client.go index 9cae664..61f5f0e 100644 --- a/internal/pkg/rancher/client/namespace_client.go +++ b/internal/pkg/rancher/client/namespace_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendClusterClient "github.com/rancher/types/client/cluster/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/namespace_client_test.go b/internal/pkg/rancher/client/namespace_client_test.go index 3f9b590..ee44095 100644 --- a/internal/pkg/rancher/client/namespace_client_test.go +++ b/internal/pkg/rancher/client/namespace_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendClusterClient "github.com/rancher/types/client/cluster/v3" diff --git a/internal/pkg/rancher/client/persistent_volume_client.go b/internal/pkg/rancher/client/persistent_volume_client.go index 8e55897..0ed1af3 100644 --- a/internal/pkg/rancher/client/persistent_volume_client.go +++ b/internal/pkg/rancher/client/persistent_volume_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendClusterClient "github.com/rancher/types/client/cluster/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/persistent_volume_client_test.go b/internal/pkg/rancher/client/persistent_volume_client_test.go index dc8e759..23acaac 100644 --- a/internal/pkg/rancher/client/persistent_volume_client_test.go +++ b/internal/pkg/rancher/client/persistent_volume_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendClusterClient "github.com/rancher/types/client/cluster/v3" diff --git a/internal/pkg/rancher/client/project_catalog_client.go b/internal/pkg/rancher/client/project_catalog_client.go new file mode 100644 index 0000000..01eb0b4 --- /dev/null +++ b/internal/pkg/rancher/client/project_catalog_client.go @@ -0,0 +1,172 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by cataloglicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "fmt" + + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/rancher/norman/types" + backendRancherClient "github.com/rancher/types/client/management/v3" + "github.com/sirupsen/logrus" +) + +func newProjectCatalogClientWithData( + catalog rancherModel.Catalog, + projectClient ProjectClient, + logger *logrus.Entry, +) (CatalogClient, error) { + result, err := newProjectCatalogClient( + catalog.Name, + projectClient, + logger, + ) + if err != nil { + return nil, err + } + err = result.SetData(catalog) + return result, err +} + +func newProjectCatalogClient( + name string, + projectClient ProjectClient, + logger *logrus.Entry, +) (CatalogClient, error) { + return &projectCatalogClient{ + resourceClient: resourceClient{ + name: name, + logger: logger.WithField("catalog_name", name), + }, + projectClient: projectClient, + }, nil +} + +type projectCatalogClient struct { + resourceClient + catalog rancherModel.Catalog + projectClient ProjectClient +} + +func (client *projectCatalogClient) Exists() (bool, error) { + backendClient, err := client.projectClient.backendRancherClient() + if err != nil { + return false, err + } + projectID, err := client.projectClient.ID() + if err != nil { + return false, err + } + collection, err := backendClient.ProjectCatalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "name": client.name, + "projectID": projectID, + }, + }) + if nil != err { + client.logger.WithError(err).Error("Failed to read catalog list") + return false, fmt.Errorf("Failed to read catalog list, %v", err) + } + for _, item := range collection.Data { + if item.Name == client.name { + return true, nil + } + } + client.logger.Debug("Catalog not found") + return false, nil +} + +func (client *projectCatalogClient) Create() error { + backendClient, err := client.projectClient.backendRancherClient() + if err != nil { + return err + } + projectID, err := client.projectClient.ID() + if err != nil { + return err + } + client.logger.Info("Create new catalog") + _, err = backendClient.ProjectCatalog.Create(&backendRancherClient.ProjectCatalog{ + Name: client.catalog.Name, + ProjectID: projectID, + URL: client.catalog.URL, + Branch: client.catalog.Branch, + Username: client.catalog.Username, + Password: client.catalog.Password, + Labels: map[string]string{ + "cattlectl.io/hash": hashOf(client.catalog), + }, + }) + return err +} + +func (client *projectCatalogClient) Upgrade() error { + backendClient, err := client.projectClient.backendRancherClient() + if err != nil { + return err + } + projectID, err := client.projectClient.ID() + if err != nil { + return err + } + client.logger.Trace("Load from rancher") + collection, err := backendClient.ProjectCatalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "name": client.name, + "projectID": projectID, + }, + }) + if nil != err { + client.logger.WithError(err).Error("Failed to read catalog list") + return fmt.Errorf("Failed to read catalog list, %v", err) + } + + if len(collection.Data) == 0 { + return fmt.Errorf("Catalog %v not found", client.name) + } + + existingCatalog := collection.Data[0] + if isProjectCatalogUnchanged(existingCatalog, client.catalog) { + client.logger.Debug("Skip upgrade catalog - no changes") + return nil + } + client.logger.Info("Upgrade ProjectCatalog") + existingCatalog.Labels["cattlectl.io/hash"] = hashOf(client.catalog) + existingCatalog.URL = client.catalog.URL + existingCatalog.Branch = client.catalog.Branch + existingCatalog.Username = client.catalog.Username + existingCatalog.Password = client.catalog.Password + + _, err = backendClient.ProjectCatalog.Replace(&existingCatalog) + return err +} + +func (client *projectCatalogClient) Data() (rancherModel.Catalog, error) { + return client.catalog, nil +} + +func (client *projectCatalogClient) SetData(catalog rancherModel.Catalog) error { + client.name = catalog.Name + client.catalog = catalog + return nil +} + +func isProjectCatalogUnchanged(existingCatalog backendRancherClient.ProjectCatalog, catalog rancherModel.Catalog) bool { + hash, hashExists := existingCatalog.Labels["cattlectl.io/hash"] + if !hashExists { + return false + } + return hash == hashOf(catalog) +} diff --git a/internal/pkg/rancher/client/project_catalog_client_test.go b/internal/pkg/rancher/client/project_catalog_client_test.go new file mode 100644 index 0000000..d0cbfa9 --- /dev/null +++ b/internal/pkg/rancher/client/project_catalog_client_test.go @@ -0,0 +1,269 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "fmt" + "reflect" + "testing" + + "github.com/bitgrip/cattlectl/internal/pkg/assert" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" + "github.com/rancher/norman/types" + backendRancherClient "github.com/rancher/types/client/management/v3" + "github.com/sirupsen/logrus" +) + +func Test_projectCatalogClient_Exists(t *testing.T) { + tests := []struct { + name string + client *projectCatalogClient + wanted bool + wantErr bool + wantedErr string + }{ + { + name: "Existing", + client: existingProjectCatalogClient( + t, + simpleCatalogName, + simpleProjectID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wanted: true, + wantErr: false, + }, + { + name: "Not_Existing", + client: notExistingProjectCatalogClient( + t, + simpleCatalogName, + simpleProjectID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wanted: false, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.client.Exists() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + assert.Equals(t, tt.wanted, got) + } + }) + } +} + +func Test_projectCatalogClient_Create(t *testing.T) { + tests := []struct { + name string + client *projectCatalogClient + wantErr bool + wantedErr string + }{ + { + name: "Create", + client: notExistingProjectCatalogClient( + t, + simpleCatalogName, + simpleProjectID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.client.Create() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + } + }) + } +} + +func Test_projectCatalogClient_Upgrade(t *testing.T) { + tests := []struct { + name string + client *projectCatalogClient + wantErr bool + wantedErr string + }{ + { + name: "Create", + client: existingProjectCatalogClient( + t, + simpleCatalogName, + simpleProjectID, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.client.Upgrade() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + } + }) + } +} + +func existingProjectCatalogClient(t *testing.T, name, projectID, url, branch, username, password string) *projectCatalogClient { + testClients := stubs.CreateBackendStubs(t) + expectedListOpts := &types.ListOpts{ + Filters: map[string]interface{}{ + "name": name, + "projectID": projectID, + }, + } + projectCatalogData := rancherModel.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + } + expectedBackendrCatalog := &backendRancherClient.ProjectCatalog{ + Name: name, + ProjectID: projectID, + URL: url, + Branch: branch, + Username: username, + Password: password, + Labels: map[string]string{"cattlectl.io/hash": "d20875c8c699ed126b385992bf8fc7c384f18e85"}, + } + + projectCatalogOperationsStub := stubs.CreateProjectCatalogOperationsStub(t) + projectCatalogOperationsStub.DoList = func(opts *types.ListOpts) (*backendRancherClient.ProjectCatalogCollection, error) { + if !reflect.DeepEqual(expectedListOpts, opts) { + return nil, fmt.Errorf("Unexpected ListOpts %v", opts) + } + return &backendRancherClient.ProjectCatalogCollection{ + Data: []backendRancherClient.ProjectCatalog{ + backendRancherClient.ProjectCatalog{ + Name: name, + ProjectID: projectID, + Labels: map[string]string{}, + }, + }, + }, nil + } + projectCatalogOperationsStub.DoReplace = func(existing *backendRancherClient.ProjectCatalog) (*backendRancherClient.ProjectCatalog, error) { + if !reflect.DeepEqual(expectedBackendrCatalog, existing) { + return nil, fmt.Errorf("Unexpected ProjectCatalog %v", existing) + } + return existing, nil + } + testClients.ManagementClient.ProjectCatalog = projectCatalogOperationsStub + rancherClient := simpleRancherClient() + rancherClient._backendRancherClient = testClients.ManagementClient + clusterClient := simpleClusterClient() + clusterClient.rancherClient = rancherClient + projectClient := simpleProjectClient() + projectClient.clusterClient = clusterClient + projectClient._backendProjectClient = testClients.ProjectClient + result, err := newProjectCatalogClient( + name, + projectClient, + logrus.New().WithFields(logrus.Fields{}), + ) + assert.Ok(t, err) + projectCatalogClientResult := result.(*projectCatalogClient) + projectCatalogClientResult.catalog = projectCatalogData + return projectCatalogClientResult +} + +func notExistingProjectCatalogClient(t *testing.T, name, projectID, url, branch, username, password string) *projectCatalogClient { + testClients := stubs.CreateBackendStubs(t) + expectedListOpts := &types.ListOpts{ + Filters: map[string]interface{}{ + "name": name, + "projectID": projectID, + }, + } + projectCatalogData := rancherModel.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + } + expectedBackendrCatalog := &backendRancherClient.ProjectCatalog{ + Name: name, + ProjectID: projectID, + URL: url, + Branch: branch, + Username: username, + Password: password, + Labels: map[string]string{"cattlectl.io/hash": hashOf(projectCatalogData)}, + } + + projectCatalogOperationsStub := stubs.CreateProjectCatalogOperationsStub(t) + projectCatalogOperationsStub.DoList = func(opts *types.ListOpts) (*backendRancherClient.ProjectCatalogCollection, error) { + if !reflect.DeepEqual(expectedListOpts, opts) { + return nil, fmt.Errorf("Unexpected ListOpts %v", opts) + } + return &backendRancherClient.ProjectCatalogCollection{ + Data: []backendRancherClient.ProjectCatalog{}, + }, nil + } + projectCatalogOperationsStub.DoCreate = func(projectCatalog *backendRancherClient.ProjectCatalog) (*backendRancherClient.ProjectCatalog, error) { + if !reflect.DeepEqual(expectedBackendrCatalog, projectCatalog) { + return nil, fmt.Errorf("Unexpected Catalog %v", projectCatalog) + } + + return projectCatalog, nil + } + testClients.ManagementClient.ProjectCatalog = projectCatalogOperationsStub + rancherClient := simpleRancherClient() + rancherClient._backendRancherClient = testClients.ManagementClient + clusterClient := simpleClusterClient() + clusterClient.rancherClient = rancherClient + projectClient := simpleProjectClient() + projectClient.clusterClient = clusterClient + projectClient._backendProjectClient = testClients.ProjectClient + result, err := newProjectCatalogClient( + name, + projectClient, + logrus.New().WithFields(logrus.Fields{}), + ) + assert.Ok(t, err) + projectCatalogClientResult := result.(*projectCatalogClient) + projectCatalogClientResult.catalog = projectCatalogData + return projectCatalogClientResult +} diff --git a/internal/pkg/rancher/client/project_client.go b/internal/pkg/rancher/client/project_client.go index 2a4b6b8..e1dab2a 100644 --- a/internal/pkg/rancher/client/project_client.go +++ b/internal/pkg/rancher/client/project_client.go @@ -17,8 +17,9 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" + backendClusterClient "github.com/rancher/types/client/cluster/v3" backendRancherClient "github.com/rancher/types/client/management/v3" backendProjectClient "github.com/rancher/types/client/project/v3" "github.com/sirupsen/logrus" @@ -49,6 +50,7 @@ func newProjectClient( deploymentClients: make(map[string]DeploymentClient), daemonSetClients: make(map[string]DaemonSetClient), statefulSetClients: make(map[string]StatefulSetClient), + catalogClients: make(map[string]CatalogClient), }, nil } @@ -68,6 +70,7 @@ type projectClient struct { deploymentClients map[string]DeploymentClient daemonSetClients map[string]DaemonSetClient statefulSetClients map[string]StatefulSetClient + catalogClients map[string]CatalogClient } func (client *projectClient) init() error { @@ -690,6 +693,56 @@ func (client *projectClient) StatefulSets(namespaceName string) ([]StatefulSetCl return result, nil } +func (client *projectClient) Catalog(catalogName string) (CatalogClient, error) { + if cache, exists := client.catalogClients[catalogName]; exists { + return cache, nil + } + result, err := newProjectCatalogClient(catalogName, client, client.logger) + if err != nil { + return nil, err + } + client.catalogClients[catalogName] = result + return result, nil +} + +func (client *projectClient) Catalogs() ([]CatalogClient, error) { + backendRancherClient, err := client.backendRancherClient() + if err != nil { + return nil, err + } + collection, err := backendRancherClient.ProjectCatalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "projectId": client.id, + }, + }) + if err != nil { + return nil, err + } + result := make([]CatalogClient, len(collection.Data)) + for i, backendCatalog := range collection.Data { + catalog, err := client.Catalog(backendCatalog.Name) + if err != nil { + return nil, err + } + result[i] = catalog + } + return result, nil +} + +func (client *projectClient) backendRancherClient() (*backendRancherClient.Client, error) { + if err := client.init(); err != nil { + return nil, err + } + return client.clusterClient.backendRancherClient() +} + +func (client *projectClient) backendClusterClient() (*backendClusterClient.Client, error) { + if err := client.init(); err != nil { + return nil, err + } + return client.clusterClient.backendClusterClient() +} + func (client *projectClient) backendProjectClient() (*backendProjectClient.Client, error) { if err := client.init(); err != nil { return nil, err diff --git a/internal/pkg/rancher/client/project_client_test.go b/internal/pkg/rancher/client/project_client_test.go index 46e932e..fb1e21b 100644 --- a/internal/pkg/rancher/client/project_client_test.go +++ b/internal/pkg/rancher/client/project_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendRancherClient "github.com/rancher/types/client/management/v3" @@ -1654,6 +1654,7 @@ func simpleProjectClient() *projectClient { deploymentClients: make(map[string]DeploymentClient), daemonSetClients: make(map[string]DaemonSetClient), statefulSetClients: make(map[string]StatefulSetClient), + catalogClients: make(map[string]CatalogClient), } } diff --git a/internal/pkg/rancher/client/rancher_catalog_client.go b/internal/pkg/rancher/client/rancher_catalog_client.go new file mode 100644 index 0000000..65df40c --- /dev/null +++ b/internal/pkg/rancher/client/rancher_catalog_client.go @@ -0,0 +1,158 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by cataloglicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "fmt" + + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/rancher/norman/types" + backendRancherClient "github.com/rancher/types/client/management/v3" + "github.com/sirupsen/logrus" +) + +func newRancherCatalogClientWithData( + catalog rancherModel.Catalog, + rancherClient RancherClient, + logger *logrus.Entry, +) (CatalogClient, error) { + result, err := newRancherCatalogClient( + catalog.Name, + rancherClient, + logger, + ) + if err != nil { + return nil, err + } + err = result.SetData(catalog) + return result, err +} + +func newRancherCatalogClient( + name string, + rancherClient RancherClient, + logger *logrus.Entry, +) (CatalogClient, error) { + return &rancherCatalogClient{ + resourceClient: resourceClient{ + name: name, + logger: logger.WithField("catalog_name", name), + }, + rancherClient: rancherClient, + }, nil +} + +type rancherCatalogClient struct { + resourceClient + catalog rancherModel.Catalog + rancherClient RancherClient +} + +func (client *rancherCatalogClient) Exists() (bool, error) { + backendClient, err := client.rancherClient.backendRancherClient() + if err != nil { + return false, err + } + collection, err := backendClient.Catalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "name": client.name, + }, + }) + if nil != err { + client.logger.WithError(err).Error("Failed to read catalog list") + return false, fmt.Errorf("Failed to read catalog list, %v", err) + } + for _, item := range collection.Data { + if item.Name == client.name { + return true, nil + } + } + client.logger.Debug("Catalog not found") + return false, nil +} + +func (client *rancherCatalogClient) Create() error { + backendClient, err := client.rancherClient.backendRancherClient() + if err != nil { + return err + } + + client.logger.Info("Create new catalog") + _, err = backendClient.Catalog.Create(&backendRancherClient.Catalog{ + Name: client.catalog.Name, + URL: client.catalog.URL, + Branch: client.catalog.Branch, + Username: client.catalog.Username, + Password: client.catalog.Password, + Labels: map[string]string{ + "cattlectl.io/hash": hashOf(client.catalog), + }, + }) + return err +} + +func (client *rancherCatalogClient) Upgrade() error { + backendClient, err := client.rancherClient.backendRancherClient() + if err != nil { + return err + } + client.logger.Trace("Load from rancher") + collection, err := backendClient.Catalog.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "name": client.name, + }, + }) + if nil != err { + client.logger.WithError(err).Error("Failed to read catalog list") + return fmt.Errorf("Failed to read catalog list, %v", err) + } + + if len(collection.Data) == 0 { + return fmt.Errorf("Catalog %v not found", client.name) + } + + existingCatalog := collection.Data[0] + if isRancherCatalogUnchanged(existingCatalog, client.catalog) { + client.logger.Debug("Skip upgrade catalog - no changes") + return nil + } + client.logger.Info("Upgrade Catalog") + existingCatalog.Labels["cattlectl.io/hash"] = hashOf(client.catalog) + existingCatalog.URL = client.catalog.URL + existingCatalog.Branch = client.catalog.Branch + existingCatalog.Username = client.catalog.Username + existingCatalog.Password = client.catalog.Password + + _, err = backendClient.Catalog.Replace(&existingCatalog) + return err +} + +func (client *rancherCatalogClient) Data() (rancherModel.Catalog, error) { + return client.catalog, nil +} + +func (client *rancherCatalogClient) SetData(catalog rancherModel.Catalog) error { + client.name = catalog.Name + client.catalog = catalog + return nil +} + +func isRancherCatalogUnchanged(existingCatalog backendRancherClient.Catalog, catalog rancherModel.Catalog) bool { + hash, hashExists := existingCatalog.Labels["cattlectl.io/hash"] + if !hashExists { + return false + } + return hash == hashOf(catalog) +} diff --git a/internal/pkg/rancher/client/rancher_catalog_client_test.go b/internal/pkg/rancher/client/rancher_catalog_client_test.go new file mode 100644 index 0000000..1947d29 --- /dev/null +++ b/internal/pkg/rancher/client/rancher_catalog_client_test.go @@ -0,0 +1,258 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package client + +import ( + "fmt" + "reflect" + "testing" + + "github.com/bitgrip/cattlectl/internal/pkg/assert" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" + "github.com/rancher/norman/types" + backendRancherClient "github.com/rancher/types/client/management/v3" + "github.com/sirupsen/logrus" +) + +const ( + simpleCatalogName = "simple-catalog" + simpleURL = "http://simple-url" + simpleBranch = "simple-branch" + simpleUsername = "simple-username" + simplePassword = "simplePassword" +) + +func Test_rancherCatalogClient_Exists(t *testing.T) { + tests := []struct { + name string + client *rancherCatalogClient + wanted bool + wantErr bool + wantedErr string + }{ + { + name: "Existing", + client: existingRancherCatalogClient( + t, + simpleCatalogName, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wanted: true, + wantErr: false, + }, + { + name: "Not_Existing", + client: notExistingRancherCatalogClient( + t, + simpleCatalogName, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wanted: false, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.client.Exists() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + assert.Equals(t, tt.wanted, got) + } + }) + } +} + +func Test_rancherCatalogClient_Create(t *testing.T) { + tests := []struct { + name string + client *rancherCatalogClient + wantErr bool + wantedErr string + }{ + { + name: "Create", + client: notExistingRancherCatalogClient( + t, + simpleCatalogName, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.client.Create() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + } + }) + } +} + +func Test_rancherCatalogClient_Upgrade(t *testing.T) { + tests := []struct { + name string + client *rancherCatalogClient + wantErr bool + wantedErr string + }{ + { + name: "Create", + client: existingRancherCatalogClient( + t, + simpleCatalogName, + simpleURL, + simpleBranch, + simpleUsername, + simplePassword, + ), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.client.Upgrade() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + } + }) + } +} + +func existingRancherCatalogClient(t *testing.T, name, url, branch, username, password string) *rancherCatalogClient { + testClients := stubs.CreateBackendStubs(t) + expectedListOpts := &types.ListOpts{ + Filters: map[string]interface{}{ + "name": name, + }, + } + rancherCatalogData := rancherModel.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + } + expectedBackendrCatalog := &backendRancherClient.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + Labels: map[string]string{"cattlectl.io/hash": "d20875c8c699ed126b385992bf8fc7c384f18e85"}, + } + + rancherCatalogOperationsStub := stubs.CreateRancherCatalogOperationsStub(t) + rancherCatalogOperationsStub.DoList = func(opts *types.ListOpts) (*backendRancherClient.CatalogCollection, error) { + if !reflect.DeepEqual(expectedListOpts, opts) { + return nil, fmt.Errorf("Unexpected ListOpts %v", opts) + } + return &backendRancherClient.CatalogCollection{ + Data: []backendRancherClient.Catalog{ + backendRancherClient.Catalog{ + Name: name, + Labels: map[string]string{}, + }, + }, + }, nil + } + rancherCatalogOperationsStub.DoReplace = func(existing *backendRancherClient.Catalog) (*backendRancherClient.Catalog, error) { + if !reflect.DeepEqual(expectedBackendrCatalog, existing) { + return nil, fmt.Errorf("Unexpected ListOpts %v", existing) + } + return existing, nil + } + testClients.ManagementClient.Catalog = rancherCatalogOperationsStub + rancherClient := simpleRancherClient() + rancherClient._backendRancherClient = testClients.ManagementClient + result, err := newRancherCatalogClient( + name, + rancherClient, + logrus.New().WithFields(logrus.Fields{}), + ) + assert.Ok(t, err) + rancherCatalogClientResult := result.(*rancherCatalogClient) + rancherCatalogClientResult.catalog = rancherCatalogData + return rancherCatalogClientResult +} + +func notExistingRancherCatalogClient(t *testing.T, name, url, branch, username, password string) *rancherCatalogClient { + testClients := stubs.CreateBackendStubs(t) + expectedListOpts := &types.ListOpts{ + Filters: map[string]interface{}{ + "name": name, + }, + } + rancherCatalogData := rancherModel.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + } + expectedBackendrCatalog := &backendRancherClient.Catalog{ + Name: name, + URL: url, + Branch: branch, + Username: username, + Password: password, + Labels: map[string]string{"cattlectl.io/hash": hashOf(rancherCatalogData)}, + } + + rancherCatalogOperationsStub := stubs.CreateRancherCatalogOperationsStub(t) + rancherCatalogOperationsStub.DoList = func(opts *types.ListOpts) (*backendRancherClient.CatalogCollection, error) { + if !reflect.DeepEqual(expectedListOpts, opts) { + return nil, fmt.Errorf("Unexpected ListOpts %v", opts) + } + return &backendRancherClient.CatalogCollection{ + Data: []backendRancherClient.Catalog{}, + }, nil + } + rancherCatalogOperationsStub.DoCreate = func(rancherCatalog *backendRancherClient.Catalog) (*backendRancherClient.Catalog, error) { + if !reflect.DeepEqual(expectedBackendrCatalog, rancherCatalog) { + return nil, fmt.Errorf("Unexpected Catalog %v", rancherCatalog) + } + + return rancherCatalog, nil + } + testClients.ManagementClient.Catalog = rancherCatalogOperationsStub + rancherClient := simpleRancherClient() + rancherClient._backendRancherClient = testClients.ManagementClient + result, err := newRancherCatalogClient( + name, + rancherClient, + logrus.New().WithFields(logrus.Fields{}), + ) + assert.Ok(t, err) + rancherCatalogClientResult := result.(*rancherCatalogClient) + rancherCatalogClientResult.catalog = rancherCatalogData + return rancherCatalogClientResult +} diff --git a/internal/pkg/rancher/client/rancher_client.go b/internal/pkg/rancher/client/rancher_client.go index d88641c..5902453 100644 --- a/internal/pkg/rancher/client/rancher_client.go +++ b/internal/pkg/rancher/client/rancher_client.go @@ -26,6 +26,7 @@ func NewRancherClient(config RancherConfig) (RancherClient, error) { config: config, logger: logrus.WithFields(logrus.Fields{}), clusterClients: make(map[string]ClusterClient), + catalogClients: make(map[string]CatalogClient), }, nil } @@ -44,6 +45,7 @@ type rancherClient struct { _backendRancherClient *backendRancherClient.Client logger *logrus.Entry clusterClients map[string]ClusterClient + catalogClients map[string]CatalogClient } func (client *rancherClient) init() error { @@ -92,6 +94,40 @@ func (client *rancherClient) Clusters() ([]ClusterClient, error) { return result, nil } +func (client *rancherClient) Catalog(catalogName string) (CatalogClient, error) { + if cache, exists := client.catalogClients[catalogName]; exists { + return cache, nil + } + result, err := newRancherCatalogClient(catalogName, client, client.logger) + if err != nil { + return nil, err + } + client.catalogClients[catalogName] = result + return result, nil +} + +func (client *rancherClient) Catalogs() ([]CatalogClient, error) { + backendRancherClient, err := client.backendRancherClient() + if err != nil { + return nil, err + } + collection, err := backendRancherClient.Catalog.List(&types.ListOpts{ + Filters: map[string]interface{}{}, + }) + if err != nil { + return nil, err + } + result := make([]CatalogClient, len(collection.Data)) + for i, backendCatalog := range collection.Data { + catalog, err := client.Catalog(backendCatalog.Name) + if err != nil { + return nil, err + } + result[i] = catalog + } + return result, nil +} + func (client *rancherClient) backendRancherClient() (*backendRancherClient.Client, error) { if err := client.init(); err != nil { return nil, err diff --git a/internal/pkg/rancher/client/rancher_client_test.go b/internal/pkg/rancher/client/rancher_client_test.go index c4f1706..d08ca7f 100644 --- a/internal/pkg/rancher/client/rancher_client_test.go +++ b/internal/pkg/rancher/client/rancher_client_test.go @@ -20,6 +20,7 @@ import ( "github.com/bitgrip/cattlectl/internal/pkg/assert" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" + backendRancherClient "github.com/rancher/types/client/management/v3" managementClient "github.com/rancher/types/client/management/v3" "github.com/sirupsen/logrus" ) @@ -104,11 +105,104 @@ func Test_rancherClient_Clusters(t *testing.T) { } } +func Test_rancherClient_Catalog(t *testing.T) { + type args struct { + name string + } + tests := []struct { + name string + client *projectClient + args args + wantErr bool + wantedErr string + }{ + { + name: simpleClusterName, + client: simpleProjectClient(), + args: args{ + name: simpleNamespaceName, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + // Arrange + testClients := stubs.CreateBackendStubs(t) + rancherClient := simpleRancherClient() + clusterClient := simpleClusterClient() + rancherClient._backendRancherClient = testClients.ManagementClient + clusterClient.rancherClient = rancherClient + clusterClient._backendClusterClient = testClients.ClusterClient + tt.client.clusterClient = clusterClient + tt.client._backendProjectClient = testClients.ProjectClient + + got, err := tt.client.Namespace(tt.args.name) + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + gotName, err := got.Name() + assert.Ok(t, err) + assert.Equals(t, tt.args.name, gotName) + } + got2, err := tt.client.Namespace(tt.args.name) + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + assert.Assert(t, got == got2, "second call shout returne the same object from cache") + } + }) + } +} + +func Test_rancherClient_Catalogs(t *testing.T) { + tests := []struct { + name string + client *rancherClient + foundCatalogs []string + wantedLength int + wantErr bool + wantedErr string + }{ + { + name: "success", + client: simpleRancherClient(), + foundCatalogs: []string{simpleCatalogName + "1", simpleCatalogName + "2"}, + wantedLength: 2, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + // Arrange + testClients := stubs.CreateBackendStubs(t) + tt.client._backendRancherClient = testClients.ManagementClient + + catalogOperationStub := stubs.CreateRancherCatalogOperationsStub(t) + catalogOperationStub.DoList = foundCatalogs(tt.foundCatalogs) + testClients.ManagementClient.Catalog = catalogOperationStub + + got, err := tt.client.Catalogs() + if tt.wantErr { + assert.NotOk(t, err, tt.wantedErr) + } else { + assert.Ok(t, err) + assert.Equals(t, tt.wantedLength, len(got)) + } + }) + } +} + func simpleRancherClient() *rancherClient { return &rancherClient{ config: RancherConfig{}, logger: logrus.WithFields(logrus.Fields{}), clusterClients: make(map[string]ClusterClient), + catalogClients: make(map[string]CatalogClient), } } @@ -122,3 +216,15 @@ func twoClusters() func(opts *types.ListOpts) (*managementClient.ClusterCollecti }, nil } } + +func foundCatalogs(names []string) func(opts *types.ListOpts) (*backendRancherClient.CatalogCollection, error) { + data := make([]backendRancherClient.Catalog, 0) + for _, name := range names { + data = append(data, backendRancherClient.Catalog{Name: name}) + } + return func(opts *types.ListOpts) (*backendRancherClient.CatalogCollection, error) { + return &backendRancherClient.CatalogCollection{ + Data: data, + }, nil + } +} diff --git a/internal/pkg/rancher/client/resource_client.go b/internal/pkg/rancher/client/resource_client.go index 5bab26a..b409c27 100644 --- a/internal/pkg/rancher/client/resource_client.go +++ b/internal/pkg/rancher/client/resource_client.go @@ -20,6 +20,9 @@ import ( "github.com/sirupsen/logrus" ) +// EmptyResourceClient is a ResourceClient with always exists and dose nothing +var EmptyResourceClient = emptyResourceClient{} + type resourceClient struct { id string name string @@ -73,3 +76,22 @@ func (client *namespacedResourceClient) NamespaceID() (string, error) { func (client *namespacedResourceClient) Namespace() (string, error) { return client.namespace, nil } + +type emptyResourceClient struct{} + +func (client emptyResourceClient) ID() (string, error) { + return "", nil +} +func (client emptyResourceClient) Name() (string, error) { + return "", nil +} + +func (client emptyResourceClient) Exists() (bool, error) { + return true, nil +} +func (client emptyResourceClient) Create() error { + return nil +} +func (client emptyResourceClient) Upgrade() error { + return nil +} diff --git a/internal/pkg/rancher/client/secret_client.go b/internal/pkg/rancher/client/secret_client.go index 5e79915..04163d8 100644 --- a/internal/pkg/rancher/client/secret_client.go +++ b/internal/pkg/rancher/client/secret_client.go @@ -18,7 +18,7 @@ import ( "fmt" "reflect" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/secret_client_test.go b/internal/pkg/rancher/client/secret_client_test.go index c27aa2c..a91a4ff 100644 --- a/internal/pkg/rancher/client/secret_client_test.go +++ b/internal/pkg/rancher/client/secret_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/stateful_set_client.go b/internal/pkg/rancher/client/stateful_set_client.go index dcbafdc..be4b35d 100644 --- a/internal/pkg/rancher/client/stateful_set_client.go +++ b/internal/pkg/rancher/client/stateful_set_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" "github.com/sirupsen/logrus" ) diff --git a/internal/pkg/rancher/client/stateful_set_client_test.go b/internal/pkg/rancher/client/stateful_set_client_test.go index 402c243..1e3d604 100644 --- a/internal/pkg/rancher/client/stateful_set_client_test.go +++ b/internal/pkg/rancher/client/stateful_set_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendProjectClient "github.com/rancher/types/client/project/v3" diff --git a/internal/pkg/rancher/client/storage_class_client.go b/internal/pkg/rancher/client/storage_class_client.go index b84586a..f533abc 100644 --- a/internal/pkg/rancher/client/storage_class_client.go +++ b/internal/pkg/rancher/client/storage_class_client.go @@ -17,7 +17,7 @@ package client import ( "fmt" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/rancher/norman/types" backendClusterClient "github.com/rancher/types/client/cluster/v3" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/client/storage_class_client_test.go b/internal/pkg/rancher/client/storage_class_client_test.go index 7144f0c..ea6959c 100644 --- a/internal/pkg/rancher/client/storage_class_client_test.go +++ b/internal/pkg/rancher/client/storage_class_client_test.go @@ -20,7 +20,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/stubs" "github.com/rancher/norman/types" backendClusterClient "github.com/rancher/types/client/cluster/v3" diff --git a/internal/pkg/rancher/cluster/cluster_converger.go b/internal/pkg/rancher/cluster/cluster_converger.go new file mode 100644 index 0000000..8222b22 --- /dev/null +++ b/internal/pkg/rancher/cluster/cluster_converger.go @@ -0,0 +1,44 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rancher + +import ( + "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" + clusterModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/model" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" +) + +// NewClusterConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/model.Cluster +func NewClusterConverger(cluster clusterModel.Cluster, rancherClient client.RancherClient) (descriptor.Converger, error) { + clusterClient, err := rancherClient.Cluster(cluster.Metadata.Name) + if err != nil { + return nil, err + } + childConvergers := make([]descriptor.Converger, 0) + for _, catalog := range cluster.Catalogs { + catalogClient, err := clusterClient.Catalog(catalog.Name) + if err != nil { + return nil, err + } + catalogClient.SetData(catalog) + childConvergers = append(childConvergers, &descriptor.ResourceClientConverger{ + Client: catalogClient, + }) + } + return &descriptor.ResourceClientConverger{ + Client: client.EmptyResourceClient, + Children: childConvergers, + }, nil +} diff --git a/internal/pkg/rancher/cluster/cluster_parser.go b/internal/pkg/rancher/cluster/cluster_parser.go new file mode 100644 index 0000000..2a807f1 --- /dev/null +++ b/internal/pkg/rancher/cluster/cluster_parser.go @@ -0,0 +1,29 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rancher + +import ( + "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/sirupsen/logrus" +) + +// NewClusterParser creates a Parser that is printing prettified representations +func NewClusterParser(descriptorFile string, values map[string]interface{}) descriptor.Parser { + logger := logrus.WithFields(logrus.Fields{ + "descriptor_file": descriptorFile, + }) + return descriptor.NewLogginParser(rancherModel.ClusterKind, logger, values) +} diff --git a/internal/pkg/rancher/cluster/model/cluster.go b/internal/pkg/rancher/cluster/model/cluster.go new file mode 100644 index 0000000..bb2c118 --- /dev/null +++ b/internal/pkg/rancher/cluster/model/cluster.go @@ -0,0 +1,37 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" +) + +// Cluster represents global members +type Cluster struct { + APIVersion string `yaml:"api_version"` + Kind string `yaml:"kind"` + Metadata ClusterMetadata `yaml:"metadata"` + Catalogs []rancherModel.Catalog `yaml:"catalogs,omitempty"` +} + +// ClusterrMetadata are global meta informations +type ClusterMetadata struct { + Name string `yaml:"name"` + ID string `yaml:"id,omitempty"` + RancherURL string `yaml:"rancher_url,omitempty"` + AccessKey string `yaml:"access_key,omitempty"` + SecretKey string `yaml:"secret_key,omitempty"` + TokenKey string `yaml:"token_key,omitempty"` +} diff --git a/internal/pkg/rancher/project/converger_test.go b/internal/pkg/rancher/cluster/project/converger_test.go similarity index 100% rename from internal/pkg/rancher/project/converger_test.go rename to internal/pkg/rancher/cluster/project/converger_test.go diff --git a/internal/pkg/rancher/project/cronjob_converger.go b/internal/pkg/rancher/cluster/project/cronjob_converger.go similarity index 98% rename from internal/pkg/rancher/project/cronjob_converger.go rename to internal/pkg/rancher/cluster/project/cronjob_converger.go index 1fa438e..8c7d63a 100644 --- a/internal/pkg/rancher/project/cronjob_converger.go +++ b/internal/pkg/rancher/cluster/project/cronjob_converger.go @@ -17,7 +17,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" ) // NewCronJobConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/projectModel.JobDescriptor diff --git a/internal/pkg/rancher/project/cronjob_converger_test.go b/internal/pkg/rancher/cluster/project/cronjob_converger_test.go similarity index 100% rename from internal/pkg/rancher/project/cronjob_converger_test.go rename to internal/pkg/rancher/cluster/project/cronjob_converger_test.go diff --git a/internal/pkg/rancher/project/cronjob_parser.go b/internal/pkg/rancher/cluster/project/cronjob_parser.go similarity index 87% rename from internal/pkg/rancher/project/cronjob_parser.go rename to internal/pkg/rancher/cluster/project/cronjob_parser.go index cdd7adc..187cedf 100644 --- a/internal/pkg/rancher/project/cronjob_parser.go +++ b/internal/pkg/rancher/cluster/project/cronjob_parser.go @@ -16,7 +16,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" "github.com/sirupsen/logrus" ) @@ -25,5 +25,5 @@ func NewCronJobParser(descriptorFile string, values map[string]interface{}) desc logger := logrus.WithFields(logrus.Fields{ "descriptor_file": descriptorFile, }) - return descriptor.NewLogginParser(projectModel.CronJobKind, logger, values) + return descriptor.NewLogginParser(rancherModel.CronJobKind, logger, values) } diff --git a/internal/pkg/rancher/project/daemonset_converger.go b/internal/pkg/rancher/cluster/project/daemonset_converger.go similarity index 98% rename from internal/pkg/rancher/project/daemonset_converger.go rename to internal/pkg/rancher/cluster/project/daemonset_converger.go index 552a404..9eca6cd 100644 --- a/internal/pkg/rancher/project/daemonset_converger.go +++ b/internal/pkg/rancher/cluster/project/daemonset_converger.go @@ -17,7 +17,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" ) // NewDaemonSetConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/projectModel.JobDescriptor diff --git a/internal/pkg/rancher/project/daemonset_converger_test.go b/internal/pkg/rancher/cluster/project/daemonset_converger_test.go similarity index 100% rename from internal/pkg/rancher/project/daemonset_converger_test.go rename to internal/pkg/rancher/cluster/project/daemonset_converger_test.go diff --git a/internal/pkg/rancher/project/daemonset_parser.go b/internal/pkg/rancher/cluster/project/daemonset_parser.go similarity index 87% rename from internal/pkg/rancher/project/daemonset_parser.go rename to internal/pkg/rancher/cluster/project/daemonset_parser.go index 063ccff..f541a74 100644 --- a/internal/pkg/rancher/project/daemonset_parser.go +++ b/internal/pkg/rancher/cluster/project/daemonset_parser.go @@ -16,7 +16,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" "github.com/sirupsen/logrus" ) @@ -25,5 +25,5 @@ func NewDaemonSetParser(descriptorFile string, values map[string]interface{}) de logger := logrus.WithFields(logrus.Fields{ "descriptor_file": descriptorFile, }) - return descriptor.NewLogginParser(projectModel.DaemonSetKind, logger, values) + return descriptor.NewLogginParser(rancherModel.DaemonSetKind, logger, values) } diff --git a/internal/pkg/rancher/project/deployment_converger.go b/internal/pkg/rancher/cluster/project/deployment_converger.go similarity index 98% rename from internal/pkg/rancher/project/deployment_converger.go rename to internal/pkg/rancher/cluster/project/deployment_converger.go index 736f0e0..7497d46 100644 --- a/internal/pkg/rancher/project/deployment_converger.go +++ b/internal/pkg/rancher/cluster/project/deployment_converger.go @@ -17,7 +17,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" ) // NewDeploymentConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/projectModel.JobDescriptor diff --git a/internal/pkg/rancher/project/deployment_converger_test.go b/internal/pkg/rancher/cluster/project/deployment_converger_test.go similarity index 100% rename from internal/pkg/rancher/project/deployment_converger_test.go rename to internal/pkg/rancher/cluster/project/deployment_converger_test.go diff --git a/internal/pkg/rancher/project/deployment_parser.go b/internal/pkg/rancher/cluster/project/deployment_parser.go similarity index 87% rename from internal/pkg/rancher/project/deployment_parser.go rename to internal/pkg/rancher/cluster/project/deployment_parser.go index 2c1b319..ff1e302 100644 --- a/internal/pkg/rancher/project/deployment_parser.go +++ b/internal/pkg/rancher/cluster/project/deployment_parser.go @@ -16,7 +16,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" "github.com/sirupsen/logrus" ) @@ -25,5 +25,5 @@ func NewDeploymentParser(descriptorFile string, values map[string]interface{}) d logger := logrus.WithFields(logrus.Fields{ "descriptor_file": descriptorFile, }) - return descriptor.NewLogginParser(projectModel.DeploymentKind, logger, values) + return descriptor.NewLogginParser(rancherModel.DeploymentKind, logger, values) } diff --git a/internal/pkg/rancher/project/job_converger.go b/internal/pkg/rancher/cluster/project/job_converger.go similarity index 98% rename from internal/pkg/rancher/project/job_converger.go rename to internal/pkg/rancher/cluster/project/job_converger.go index f1aec27..d9a95f7 100644 --- a/internal/pkg/rancher/project/job_converger.go +++ b/internal/pkg/rancher/cluster/project/job_converger.go @@ -17,7 +17,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" ) // NewJobConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/projectModel.JobDescriptor diff --git a/internal/pkg/rancher/project/job_converger_test.go b/internal/pkg/rancher/cluster/project/job_converger_test.go similarity index 100% rename from internal/pkg/rancher/project/job_converger_test.go rename to internal/pkg/rancher/cluster/project/job_converger_test.go diff --git a/internal/pkg/rancher/project/job_parser.go b/internal/pkg/rancher/cluster/project/job_parser.go similarity index 87% rename from internal/pkg/rancher/project/job_parser.go rename to internal/pkg/rancher/cluster/project/job_parser.go index bb1f0fc..dc34762 100644 --- a/internal/pkg/rancher/project/job_parser.go +++ b/internal/pkg/rancher/cluster/project/job_parser.go @@ -16,7 +16,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" "github.com/sirupsen/logrus" ) @@ -25,5 +25,5 @@ func NewJobParser(descriptorFile string, values map[string]interface{}) descript logger := logrus.WithFields(logrus.Fields{ "descriptor_file": descriptorFile, }) - return descriptor.NewLogginParser(projectModel.JobKind, logger, values) + return descriptor.NewLogginParser(rancherModel.JobKind, logger, values) } diff --git a/internal/pkg/rancher/project/merge.go b/internal/pkg/rancher/cluster/project/merge.go similarity index 99% rename from internal/pkg/rancher/project/merge.go rename to internal/pkg/rancher/cluster/project/merge.go index aeedc66..c1a1969 100644 --- a/internal/pkg/rancher/project/merge.go +++ b/internal/pkg/rancher/cluster/project/merge.go @@ -15,7 +15,7 @@ package project import ( - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" ) // MergeProject merge two projects. diff --git a/internal/pkg/rancher/project/merge_test.go b/internal/pkg/rancher/cluster/project/merge_test.go similarity index 98% rename from internal/pkg/rancher/project/merge_test.go rename to internal/pkg/rancher/cluster/project/merge_test.go index 59d2edf..8744be9 100644 --- a/internal/pkg/rancher/project/merge_test.go +++ b/internal/pkg/rancher/cluster/project/merge_test.go @@ -19,7 +19,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" yaml "gopkg.in/yaml.v2" ) diff --git a/internal/pkg/rancher/project/model/model.go b/internal/pkg/rancher/cluster/project/model/model.go similarity index 75% rename from internal/pkg/rancher/project/model/model.go rename to internal/pkg/rancher/cluster/project/model/model.go index 9da141f..b0bc78b 100644 --- a/internal/pkg/rancher/project/model/model.go +++ b/internal/pkg/rancher/cluster/project/model/model.go @@ -14,46 +14,21 @@ package model -// Types of Descriptors which are expected values of the field Cluster.Kind -const ( - ProjectKind = "Project" - JobKind = "Job" - CronJobKind = "CronJob" - DeploymentKind = "Deployment" - DaemonSetKind = "DaemonSet" - StatefulSetKind = "StatefulSet" +import ( + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" ) -// Cluster is WIP -type Cluster struct { - APIVersion string `yaml:"api_version"` - Kind string - Metadata ClusterMetadata - StorageClasses []StorageClass `yaml:"storage_classes,omitempty"` - PersistentVolumes []PersistentVolume `yaml:"storage_class,omitempty"` - Projects []Project -} - -// ClusterMetadata is WIP -type ClusterMetadata struct { - Name string - ID string `yaml:"id,omitempty"` - RancherURL string `yaml:"rancher_url,omitempty"` - AccessKey string `yaml:"access_key,omitempty"` - SecretKey string `yaml:"secret_key,omitempty"` - TokenKey string `yaml:"token_key,omitempty"` -} - // Project is a subsection of a cluster type Project struct { - APIVersion string `yaml:"api_version"` - Kind string - Metadata ProjectMetadata - Namespaces []Namespace `yaml:"namespaces,omitempty"` - Resources Resources `yaml:"resources,omitempty"` - StorageClasses []StorageClass `yaml:"storage_classes,omitempty"` - PersistentVolumes []PersistentVolume `yaml:"persistent_volumes,omitempty"` - Apps []App + APIVersion string `yaml:"api_version"` + Kind string `yaml:"kind,omitempty"` + Metadata ProjectMetadata `yaml:"metadata,omitempty"` + Catalogs []rancherModel.Catalog `yaml:"catalogs,omitempty"` + Namespaces []Namespace `yaml:"namespaces,omitempty"` + Resources Resources `yaml:"resources,omitempty"` + StorageClasses []StorageClass `yaml:"storage_classes,omitempty"` + PersistentVolumes []PersistentVolume `yaml:"persistent_volumes,omitempty"` + Apps []App `yaml:"apps,omitempty"` } // ProjectMetadata the meta informations about a Project diff --git a/internal/pkg/rancher/project/model/testdata/golden-files/descriptor.cron_job.golden b/internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.cron_job.golden similarity index 100% rename from internal/pkg/rancher/project/model/testdata/golden-files/descriptor.cron_job.golden rename to internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.cron_job.golden diff --git a/internal/pkg/rancher/project/model/testdata/golden-files/descriptor.daemonSet.golden b/internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.daemonSet.golden similarity index 100% rename from internal/pkg/rancher/project/model/testdata/golden-files/descriptor.daemonSet.golden rename to internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.daemonSet.golden diff --git a/internal/pkg/rancher/project/model/testdata/golden-files/descriptor.deployment.golden b/internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.deployment.golden similarity index 100% rename from internal/pkg/rancher/project/model/testdata/golden-files/descriptor.deployment.golden rename to internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.deployment.golden diff --git a/internal/pkg/rancher/project/model/testdata/golden-files/descriptor.job.golden b/internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.job.golden similarity index 100% rename from internal/pkg/rancher/project/model/testdata/golden-files/descriptor.job.golden rename to internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.job.golden diff --git a/internal/pkg/rancher/project/model/testdata/golden-files/descriptor.statefulSet.golden b/internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.statefulSet.golden similarity index 100% rename from internal/pkg/rancher/project/model/testdata/golden-files/descriptor.statefulSet.golden rename to internal/pkg/rancher/cluster/project/model/testdata/golden-files/descriptor.statefulSet.golden diff --git a/internal/pkg/rancher/project/model/testdata/golden-files/simple-include.golden b/internal/pkg/rancher/cluster/project/model/testdata/golden-files/simple-include.golden similarity index 100% rename from internal/pkg/rancher/project/model/testdata/golden-files/simple-include.golden rename to internal/pkg/rancher/cluster/project/model/testdata/golden-files/simple-include.golden diff --git a/internal/pkg/rancher/project/model/testdata/input/cron_job.yaml b/internal/pkg/rancher/cluster/project/model/testdata/input/cron_job.yaml similarity index 100% rename from internal/pkg/rancher/project/model/testdata/input/cron_job.yaml rename to internal/pkg/rancher/cluster/project/model/testdata/input/cron_job.yaml diff --git a/internal/pkg/rancher/project/model/testdata/input/daemonSet.yaml b/internal/pkg/rancher/cluster/project/model/testdata/input/daemonSet.yaml similarity index 100% rename from internal/pkg/rancher/project/model/testdata/input/daemonSet.yaml rename to internal/pkg/rancher/cluster/project/model/testdata/input/daemonSet.yaml diff --git a/internal/pkg/rancher/project/model/testdata/input/deployment.yaml b/internal/pkg/rancher/cluster/project/model/testdata/input/deployment.yaml similarity index 100% rename from internal/pkg/rancher/project/model/testdata/input/deployment.yaml rename to internal/pkg/rancher/cluster/project/model/testdata/input/deployment.yaml diff --git a/internal/pkg/rancher/project/model/testdata/input/job.yaml b/internal/pkg/rancher/cluster/project/model/testdata/input/job.yaml similarity index 100% rename from internal/pkg/rancher/project/model/testdata/input/job.yaml rename to internal/pkg/rancher/cluster/project/model/testdata/input/job.yaml diff --git a/internal/pkg/rancher/project/model/testdata/input/statefulSet.yaml b/internal/pkg/rancher/cluster/project/model/testdata/input/statefulSet.yaml similarity index 100% rename from internal/pkg/rancher/project/model/testdata/input/statefulSet.yaml rename to internal/pkg/rancher/cluster/project/model/testdata/input/statefulSet.yaml diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/cron_job.model b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/cron_job.model similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/cron_job.model rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/cron_job.model diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/daemon_set.model b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/daemon_set.model similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/daemon_set.model rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/daemon_set.model diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/deployment.model b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/deployment.model similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/deployment.model rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/deployment.model diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/deployment.yaml b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/deployment.yaml similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/deployment.yaml rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/deployment.yaml diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/job.model b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/job.model similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/job.model rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/job.model diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/job.yaml b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/job.yaml similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/job.yaml rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/job.yaml diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/stateful_set.model b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/stateful_set.model similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/stateful_set.model rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/stateful_set.model diff --git a/internal/pkg/rancher/project/model/testdata/model/workload/workload.model b/internal/pkg/rancher/cluster/project/model/testdata/model/workload/workload.model similarity index 100% rename from internal/pkg/rancher/project/model/testdata/model/workload/workload.model rename to internal/pkg/rancher/cluster/project/model/testdata/model/workload/workload.model diff --git a/internal/pkg/rancher/project/model/util.go b/internal/pkg/rancher/cluster/project/model/util.go similarity index 100% rename from internal/pkg/rancher/project/model/util.go rename to internal/pkg/rancher/cluster/project/model/util.go diff --git a/internal/pkg/rancher/project/model/workload_daemonset.go b/internal/pkg/rancher/cluster/project/model/workload_daemonset.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_daemonset.go rename to internal/pkg/rancher/cluster/project/model/workload_daemonset.go diff --git a/internal/pkg/rancher/project/model/workload_daemonset_test.go b/internal/pkg/rancher/cluster/project/model/workload_daemonset_test.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_daemonset_test.go rename to internal/pkg/rancher/cluster/project/model/workload_daemonset_test.go diff --git a/internal/pkg/rancher/project/model/workload_deployment.go b/internal/pkg/rancher/cluster/project/model/workload_deployment.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_deployment.go rename to internal/pkg/rancher/cluster/project/model/workload_deployment.go diff --git a/internal/pkg/rancher/project/model/workload_deployment_test.go b/internal/pkg/rancher/cluster/project/model/workload_deployment_test.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_deployment_test.go rename to internal/pkg/rancher/cluster/project/model/workload_deployment_test.go diff --git a/internal/pkg/rancher/project/model/workload_model.go b/internal/pkg/rancher/cluster/project/model/workload_model.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_model.go rename to internal/pkg/rancher/cluster/project/model/workload_model.go diff --git a/internal/pkg/rancher/project/model/workload_model_cron_job.go b/internal/pkg/rancher/cluster/project/model/workload_model_cron_job.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_model_cron_job.go rename to internal/pkg/rancher/cluster/project/model/workload_model_cron_job.go diff --git a/internal/pkg/rancher/project/model/workload_model_cron_job_test.go b/internal/pkg/rancher/cluster/project/model/workload_model_cron_job_test.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_model_cron_job_test.go rename to internal/pkg/rancher/cluster/project/model/workload_model_cron_job_test.go diff --git a/internal/pkg/rancher/project/model/workload_model_job.go b/internal/pkg/rancher/cluster/project/model/workload_model_job.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_model_job.go rename to internal/pkg/rancher/cluster/project/model/workload_model_job.go diff --git a/internal/pkg/rancher/project/model/workload_model_job_test.go b/internal/pkg/rancher/cluster/project/model/workload_model_job_test.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_model_job_test.go rename to internal/pkg/rancher/cluster/project/model/workload_model_job_test.go diff --git a/internal/pkg/rancher/project/model/workload_model_test.go b/internal/pkg/rancher/cluster/project/model/workload_model_test.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_model_test.go rename to internal/pkg/rancher/cluster/project/model/workload_model_test.go diff --git a/internal/pkg/rancher/project/model/workload_statefulset.go b/internal/pkg/rancher/cluster/project/model/workload_statefulset.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_statefulset.go rename to internal/pkg/rancher/cluster/project/model/workload_statefulset.go diff --git a/internal/pkg/rancher/project/model/workload_statefulset_test.go b/internal/pkg/rancher/cluster/project/model/workload_statefulset_test.go similarity index 100% rename from internal/pkg/rancher/project/model/workload_statefulset_test.go rename to internal/pkg/rancher/cluster/project/model/workload_statefulset_test.go diff --git a/internal/pkg/rancher/project/parser.go b/internal/pkg/rancher/cluster/project/parser.go similarity index 99% rename from internal/pkg/rancher/project/parser.go rename to internal/pkg/rancher/cluster/project/parser.go index d7ad033..0d97d26 100644 --- a/internal/pkg/rancher/project/parser.go +++ b/internal/pkg/rancher/cluster/project/parser.go @@ -22,7 +22,7 @@ import ( "sort" "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/template" "github.com/rancher/norman/types/slice" "github.com/sirupsen/logrus" diff --git a/internal/pkg/rancher/project/parser_test.go b/internal/pkg/rancher/cluster/project/parser_test.go similarity index 98% rename from internal/pkg/rancher/project/parser_test.go rename to internal/pkg/rancher/cluster/project/parser_test.go index 1d200a9..d919ff4 100644 --- a/internal/pkg/rancher/project/parser_test.go +++ b/internal/pkg/rancher/cluster/project/parser_test.go @@ -22,7 +22,7 @@ import ( "testing" "github.com/bitgrip/cattlectl/internal/pkg/assert" - "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/template" "github.com/sirupsen/logrus" yaml "gopkg.in/yaml.v2" diff --git a/internal/pkg/rancher/project/project_converger.go b/internal/pkg/rancher/cluster/project/project_converger.go similarity index 92% rename from internal/pkg/rancher/project/project_converger.go rename to internal/pkg/rancher/cluster/project/project_converger.go index a7683ae..dbc0b13 100644 --- a/internal/pkg/rancher/project/project_converger.go +++ b/internal/pkg/rancher/cluster/project/project_converger.go @@ -16,8 +16,8 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" ) // NewProjectConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/projectModel.Project @@ -27,6 +27,16 @@ func NewProjectConverger(project projectModel.Project, clusterClient client.Clus return nil, err } childConvergers := make([]descriptor.Converger, 0) + for _, catalog := range project.Catalogs { + catalogClient, err := projectClient.Catalog(catalog.Name) + if err != nil { + return nil, err + } + catalogClient.SetData(catalog) + childConvergers = append(childConvergers, &descriptor.ResourceClientConverger{ + Client: catalogClient, + }) + } for _, namespace := range project.Namespaces { namespaceClient, err := projectClient.Namespace(namespace.Name) if err != nil { diff --git a/internal/pkg/rancher/project/project_converger_test.go b/internal/pkg/rancher/cluster/project/project_converger_test.go similarity index 100% rename from internal/pkg/rancher/project/project_converger_test.go rename to internal/pkg/rancher/cluster/project/project_converger_test.go diff --git a/internal/pkg/rancher/project/statefulset_converger.go b/internal/pkg/rancher/cluster/project/statefulset_converger.go similarity index 98% rename from internal/pkg/rancher/project/statefulset_converger.go rename to internal/pkg/rancher/cluster/project/statefulset_converger.go index 9b64012..01ba129 100644 --- a/internal/pkg/rancher/project/statefulset_converger.go +++ b/internal/pkg/rancher/cluster/project/statefulset_converger.go @@ -17,7 +17,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/cluster/project/model" ) // NewStatefulSetConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/projectModel.JobDescriptor diff --git a/internal/pkg/rancher/project/statefulset_converger_test.go b/internal/pkg/rancher/cluster/project/statefulset_converger_test.go similarity index 100% rename from internal/pkg/rancher/project/statefulset_converger_test.go rename to internal/pkg/rancher/cluster/project/statefulset_converger_test.go diff --git a/internal/pkg/rancher/project/statefulset_parser.go b/internal/pkg/rancher/cluster/project/statefulset_parser.go similarity index 87% rename from internal/pkg/rancher/project/statefulset_parser.go rename to internal/pkg/rancher/cluster/project/statefulset_parser.go index 078e9b6..07106bc 100644 --- a/internal/pkg/rancher/project/statefulset_parser.go +++ b/internal/pkg/rancher/cluster/project/statefulset_parser.go @@ -16,7 +16,7 @@ package project import ( "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" - projectModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/project/model" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" "github.com/sirupsen/logrus" ) @@ -25,5 +25,5 @@ func NewStatefulSetParser(descriptorFile string, values map[string]interface{}) logger := logrus.WithFields(logrus.Fields{ "descriptor_file": descriptorFile, }) - return descriptor.NewLogginParser(projectModel.StatefulSetKind, logger, values) + return descriptor.NewLogginParser(rancherModel.StatefulSetKind, logger, values) } diff --git a/internal/pkg/rancher/project/testdata/cycle-include/child.yaml b/internal/pkg/rancher/cluster/project/testdata/cycle-include/child.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/cycle-include/child.yaml rename to internal/pkg/rancher/cluster/project/testdata/cycle-include/child.yaml diff --git a/internal/pkg/rancher/project/testdata/cycle-include/project.yaml b/internal/pkg/rancher/cluster/project/testdata/cycle-include/project.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/cycle-include/project.yaml rename to internal/pkg/rancher/cluster/project/testdata/cycle-include/project.yaml diff --git a/internal/pkg/rancher/project/testdata/directory-include/child-directory/child.1.yaml b/internal/pkg/rancher/cluster/project/testdata/directory-include/child-directory/child.1.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/directory-include/child-directory/child.1.yaml rename to internal/pkg/rancher/cluster/project/testdata/directory-include/child-directory/child.1.yaml diff --git a/internal/pkg/rancher/project/testdata/directory-include/child-directory/child.2.yaml b/internal/pkg/rancher/cluster/project/testdata/directory-include/child-directory/child.2.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/directory-include/child-directory/child.2.yaml rename to internal/pkg/rancher/cluster/project/testdata/directory-include/child-directory/child.2.yaml diff --git a/internal/pkg/rancher/project/testdata/directory-include/project.yaml b/internal/pkg/rancher/cluster/project/testdata/directory-include/project.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/directory-include/project.yaml rename to internal/pkg/rancher/cluster/project/testdata/directory-include/project.yaml diff --git a/internal/pkg/rancher/project/testdata/files-include/child.1.yaml b/internal/pkg/rancher/cluster/project/testdata/files-include/child.1.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/files-include/child.1.yaml rename to internal/pkg/rancher/cluster/project/testdata/files-include/child.1.yaml diff --git a/internal/pkg/rancher/project/testdata/files-include/child.2.yaml b/internal/pkg/rancher/cluster/project/testdata/files-include/child.2.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/files-include/child.2.yaml rename to internal/pkg/rancher/cluster/project/testdata/files-include/child.2.yaml diff --git a/internal/pkg/rancher/project/testdata/files-include/project.yaml b/internal/pkg/rancher/cluster/project/testdata/files-include/project.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/files-include/project.yaml rename to internal/pkg/rancher/cluster/project/testdata/files-include/project.yaml diff --git a/internal/pkg/rancher/project/testdata/golden-files/cycle-include.golden b/internal/pkg/rancher/cluster/project/testdata/golden-files/cycle-include.golden similarity index 100% rename from internal/pkg/rancher/project/testdata/golden-files/cycle-include.golden rename to internal/pkg/rancher/cluster/project/testdata/golden-files/cycle-include.golden diff --git a/internal/pkg/rancher/project/testdata/golden-files/directory-include.golden b/internal/pkg/rancher/cluster/project/testdata/golden-files/directory-include.golden similarity index 100% rename from internal/pkg/rancher/project/testdata/golden-files/directory-include.golden rename to internal/pkg/rancher/cluster/project/testdata/golden-files/directory-include.golden diff --git a/internal/pkg/rancher/project/testdata/golden-files/files-include.golden b/internal/pkg/rancher/cluster/project/testdata/golden-files/files-include.golden similarity index 100% rename from internal/pkg/rancher/project/testdata/golden-files/files-include.golden rename to internal/pkg/rancher/cluster/project/testdata/golden-files/files-include.golden diff --git a/internal/pkg/rancher/project/testdata/golden-files/simple-include.golden b/internal/pkg/rancher/cluster/project/testdata/golden-files/simple-include.golden similarity index 100% rename from internal/pkg/rancher/project/testdata/golden-files/simple-include.golden rename to internal/pkg/rancher/cluster/project/testdata/golden-files/simple-include.golden diff --git a/internal/pkg/rancher/project/testdata/golden-files/valid-project.golden b/internal/pkg/rancher/cluster/project/testdata/golden-files/valid-project.golden similarity index 100% rename from internal/pkg/rancher/project/testdata/golden-files/valid-project.golden rename to internal/pkg/rancher/cluster/project/testdata/golden-files/valid-project.golden diff --git a/internal/pkg/rancher/project/testdata/include/simple/child.yaml b/internal/pkg/rancher/cluster/project/testdata/include/simple/child.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/include/simple/child.yaml rename to internal/pkg/rancher/cluster/project/testdata/include/simple/child.yaml diff --git a/internal/pkg/rancher/project/testdata/include/simple/expected.yaml b/internal/pkg/rancher/cluster/project/testdata/include/simple/expected.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/include/simple/expected.yaml rename to internal/pkg/rancher/cluster/project/testdata/include/simple/expected.yaml diff --git a/internal/pkg/rancher/project/testdata/include/simple/parent.yaml b/internal/pkg/rancher/cluster/project/testdata/include/simple/parent.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/include/simple/parent.yaml rename to internal/pkg/rancher/cluster/project/testdata/include/simple/parent.yaml diff --git a/internal/pkg/rancher/project/testdata/input/cluster.yaml b/internal/pkg/rancher/cluster/project/testdata/input/cluster.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/input/cluster.yaml rename to internal/pkg/rancher/cluster/project/testdata/input/cluster.yaml diff --git a/internal/pkg/rancher/project/testdata/input/missing-kind.yaml b/internal/pkg/rancher/cluster/project/testdata/input/missing-kind.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/input/missing-kind.yaml rename to internal/pkg/rancher/cluster/project/testdata/input/missing-kind.yaml diff --git a/internal/pkg/rancher/project/testdata/projects/all-resources.yaml b/internal/pkg/rancher/cluster/project/testdata/projects/all-resources.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/projects/all-resources.yaml rename to internal/pkg/rancher/cluster/project/testdata/projects/all-resources.yaml diff --git a/internal/pkg/rancher/project/testdata/simple-include/child.yaml b/internal/pkg/rancher/cluster/project/testdata/simple-include/child.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/simple-include/child.yaml rename to internal/pkg/rancher/cluster/project/testdata/simple-include/child.yaml diff --git a/internal/pkg/rancher/project/testdata/simple-include/project.yaml b/internal/pkg/rancher/cluster/project/testdata/simple-include/project.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/simple-include/project.yaml rename to internal/pkg/rancher/cluster/project/testdata/simple-include/project.yaml diff --git a/internal/pkg/rancher/project/testdata/valid-project/license.file b/internal/pkg/rancher/cluster/project/testdata/valid-project/license.file similarity index 100% rename from internal/pkg/rancher/project/testdata/valid-project/license.file rename to internal/pkg/rancher/cluster/project/testdata/valid-project/license.file diff --git a/internal/pkg/rancher/project/testdata/valid-project/project.yaml b/internal/pkg/rancher/cluster/project/testdata/valid-project/project.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/valid-project/project.yaml rename to internal/pkg/rancher/cluster/project/testdata/valid-project/project.yaml diff --git a/internal/pkg/rancher/project/testdata/valid-project/values.yaml b/internal/pkg/rancher/cluster/project/testdata/valid-project/values.yaml similarity index 100% rename from internal/pkg/rancher/project/testdata/valid-project/values.yaml rename to internal/pkg/rancher/cluster/project/testdata/valid-project/values.yaml diff --git a/internal/pkg/rancher/model/rancher.go b/internal/pkg/rancher/model/rancher.go new file mode 100644 index 0000000..daaea47 --- /dev/null +++ b/internal/pkg/rancher/model/rancher.go @@ -0,0 +1,52 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +// Types of Descriptors which are expected values of the field 'kind' +const ( + RancherKind = "Rancher" + ClusterKind = "Cluster" + ProjectKind = "Project" + JobKind = "Job" + CronJobKind = "CronJob" + DeploymentKind = "Deployment" + DaemonSetKind = "DaemonSet" + StatefulSetKind = "StatefulSet" +) + +// Rancher represents global members +type Rancher struct { + APIVersion string `yaml:"api_version"` + Kind string `yaml:"kind"` + Metadata RancherMetadata `yaml:"metadata"` + Catalogs []Catalog `yaml:"catalogs,omitempty"` +} + +// RancherMetadata are global meta informations +type RancherMetadata struct { + RancherURL string `yaml:"rancher_url,omitempty"` + AccessKey string `yaml:"access_key,omitempty"` + SecretKey string `yaml:"secret_key,omitempty"` + TokenKey string `yaml:"token_key,omitempty"` +} + +// Catalog is a template source to be used by Apps +type Catalog struct { + Name string `yaml:"name"` + URL string `yaml:"url"` + Branch string `yaml:"branch,omitempty"` + Username string `yaml:"username,omitempty"` + Password string `yaml:"password,omitempty"` +} diff --git a/internal/pkg/rancher/rancher_converger.go b/internal/pkg/rancher/rancher_converger.go new file mode 100644 index 0000000..3309451 --- /dev/null +++ b/internal/pkg/rancher/rancher_converger.go @@ -0,0 +1,44 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rancher + +import ( + "github.com/bitgrip/cattlectl/internal/pkg/rancher/client" + "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" +) + +// NewRancherConverger creates a Converger for a given github.com/bitgrip/cattlectl/internal/pkg/rancher/model.Rancher +func NewRancherConverger(rancher rancherModel.Rancher, rancherConfig client.RancherConfig) (descriptor.Converger, error) { + rancherClient, err := client.NewRancherClient(rancherConfig) + if err != nil { + return nil, err + } + childConvergers := make([]descriptor.Converger, 0) + for _, catalog := range rancher.Catalogs { + catalogClient, err := rancherClient.Catalog(catalog.Name) + if err != nil { + return nil, err + } + catalogClient.SetData(catalog) + childConvergers = append(childConvergers, &descriptor.ResourceClientConverger{ + Client: catalogClient, + }) + } + return &descriptor.ResourceClientConverger{ + Client: client.EmptyResourceClient, + Children: childConvergers, + }, nil +} diff --git a/internal/pkg/rancher/rancher_parser.go b/internal/pkg/rancher/rancher_parser.go new file mode 100644 index 0000000..3ab1ef5 --- /dev/null +++ b/internal/pkg/rancher/rancher_parser.go @@ -0,0 +1,29 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rancher + +import ( + "github.com/bitgrip/cattlectl/internal/pkg/rancher/descriptor" + rancherModel "github.com/bitgrip/cattlectl/internal/pkg/rancher/model" + "github.com/sirupsen/logrus" +) + +// NewRancherParser creates a Parser that is printing prettified representations +func NewRancherParser(descriptorFile string, values map[string]interface{}) descriptor.Parser { + logger := logrus.WithFields(logrus.Fields{ + "descriptor_file": descriptorFile, + }) + return descriptor.NewLogginParser(rancherModel.RancherKind, logger, values) +} diff --git a/internal/pkg/rancher/stubs/cluster_catalog_operations_stub.go b/internal/pkg/rancher/stubs/cluster_catalog_operations_stub.go new file mode 100644 index 0000000..1816399 --- /dev/null +++ b/internal/pkg/rancher/stubs/cluster_catalog_operations_stub.go @@ -0,0 +1,115 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stubs + +import ( + "testing" + + "github.com/bitgrip/cattlectl/internal/pkg/assert" + "github.com/rancher/norman/types" + rancherClient "github.com/rancher/types/client/management/v3" +) + +// CreateClusterCatalogOperationsStub creates a stub of github.com/rancher/types/client/project/v3/ClusterCatalogOperations +func CreateClusterCatalogOperationsStub(tb testing.TB) *ClusterCatalogOperationsStub { + return &ClusterCatalogOperationsStub{ + tb: tb, + DoList: func(opts *types.ListOpts) (*rancherClient.ClusterCatalogCollection, error) { + assert.FailInStub(tb, 2, "Unexpected call of List") + return nil, nil + }, + DoCreate: func(opts *rancherClient.ClusterCatalog) (*rancherClient.ClusterCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Create") + return nil, nil + }, + DoUpdate: func(existing *rancherClient.ClusterCatalog, updates interface{}) (*rancherClient.ClusterCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Update") + return nil, nil + }, + DoReplace: func(existing *rancherClient.ClusterCatalog) (*rancherClient.ClusterCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Replace") + return nil, nil + }, + DoByID: func(id string) (*rancherClient.ClusterCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of ByID") + return nil, nil + }, + DoDelete: func(container *rancherClient.ClusterCatalog) error { + assert.FailInStub(tb, 2, "Unexpected call of Delete") + return nil + }, + DoActionRefresh: func(container *rancherClient.ClusterCatalog) error { + assert.FailInStub(tb, 2, "Unexpected call of ActionRefresh") + return nil + }, + DoCollectionActionRefresh: func(container *rancherClient.ClusterCatalogCollection) error { + assert.FailInStub(tb, 2, "Unexpected call of CollectionActionRefresh") + return nil + }, + } +} + +// ClusterCatalogOperationsStub structure to hold callbacks used to stub github.com/rancher/types/client/project/v3/ClusterCatalogOperations +type ClusterCatalogOperationsStub struct { + tb testing.TB + DoList func(opts *types.ListOpts) (*rancherClient.ClusterCatalogCollection, error) + DoCreate func(opts *rancherClient.ClusterCatalog) (*rancherClient.ClusterCatalog, error) + DoUpdate func(existing *rancherClient.ClusterCatalog, updates interface{}) (*rancherClient.ClusterCatalog, error) + DoReplace func(existing *rancherClient.ClusterCatalog) (*rancherClient.ClusterCatalog, error) + DoByID func(id string) (*rancherClient.ClusterCatalog, error) + DoDelete func(container *rancherClient.ClusterCatalog) error + DoActionRefresh func(container *rancherClient.ClusterCatalog) error + DoCollectionActionRefresh func(container *rancherClient.ClusterCatalogCollection) error +} + +// List implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.List(...) +func (stub ClusterCatalogOperationsStub) List(opts *types.ListOpts) (*rancherClient.ClusterCatalogCollection, error) { + return stub.DoList(opts) +} + +// Create implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.Create(...) +func (stub ClusterCatalogOperationsStub) Create(opts *rancherClient.ClusterCatalog) (*rancherClient.ClusterCatalog, error) { + return stub.DoCreate(opts) +} + +// Update implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.Update(...) +func (stub ClusterCatalogOperationsStub) Update(existing *rancherClient.ClusterCatalog, updates interface{}) (*rancherClient.ClusterCatalog, error) { + return stub.DoUpdate(existing, updates) +} + +// Replace implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.Replace(...) +func (stub ClusterCatalogOperationsStub) Replace(existing *rancherClient.ClusterCatalog) (*rancherClient.ClusterCatalog, error) { + return stub.DoReplace(existing) +} + +// ByID implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.ByID(...) +func (stub ClusterCatalogOperationsStub) ByID(id string) (*rancherClient.ClusterCatalog, error) { + return stub.DoByID(id) +} + +// Delete implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.Delete(...) +func (stub ClusterCatalogOperationsStub) Delete(container *rancherClient.ClusterCatalog) error { + return stub.DoDelete(container) +} + +// ActionRefresh implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.ActionRefresh(...) +func (stub ClusterCatalogOperationsStub) ActionRefresh(resource *rancherClient.ClusterCatalog) error { + return stub.DoActionRefresh(resource) +} + +// CollectionActionRefresh implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.CollectionActionRefresh(...) +func (stub ClusterCatalogOperationsStub) CollectionActionRefresh(resource *rancherClient.ClusterCatalogCollection) error { + return stub.DoCollectionActionRefresh(resource) +} diff --git a/internal/pkg/rancher/stubs/project_catalog_operations_stub.go b/internal/pkg/rancher/stubs/project_catalog_operations_stub.go new file mode 100644 index 0000000..2c948bd --- /dev/null +++ b/internal/pkg/rancher/stubs/project_catalog_operations_stub.go @@ -0,0 +1,115 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stubs + +import ( + "testing" + + "github.com/bitgrip/cattlectl/internal/pkg/assert" + "github.com/rancher/norman/types" + rancherClient "github.com/rancher/types/client/management/v3" +) + +// CreateProjectCatalogOperationsStub creates a stub of github.com/rancher/types/client/project/v3/ProjectCatalogOperations +func CreateProjectCatalogOperationsStub(tb testing.TB) *ProjectCatalogOperationsStub { + return &ProjectCatalogOperationsStub{ + tb: tb, + DoList: func(opts *types.ListOpts) (*rancherClient.ProjectCatalogCollection, error) { + assert.FailInStub(tb, 2, "Unexpected call of List") + return nil, nil + }, + DoCreate: func(opts *rancherClient.ProjectCatalog) (*rancherClient.ProjectCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Create") + return nil, nil + }, + DoUpdate: func(existing *rancherClient.ProjectCatalog, updates interface{}) (*rancherClient.ProjectCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Update") + return nil, nil + }, + DoReplace: func(existing *rancherClient.ProjectCatalog) (*rancherClient.ProjectCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Replace") + return nil, nil + }, + DoByID: func(id string) (*rancherClient.ProjectCatalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of ByID") + return nil, nil + }, + DoDelete: func(container *rancherClient.ProjectCatalog) error { + assert.FailInStub(tb, 2, "Unexpected call of Delete") + return nil + }, + DoActionRefresh: func(container *rancherClient.ProjectCatalog) error { + assert.FailInStub(tb, 2, "Unexpected call of ActionRefresh") + return nil + }, + DoCollectionActionRefresh: func(container *rancherClient.ProjectCatalogCollection) error { + assert.FailInStub(tb, 2, "Unexpected call of CollectionActionRefresh") + return nil + }, + } +} + +// ProjectCatalogOperationsStub structure to hold callbacks used to stub github.com/rancher/types/client/project/v3/ProjectCatalogOperations +type ProjectCatalogOperationsStub struct { + tb testing.TB + DoList func(opts *types.ListOpts) (*rancherClient.ProjectCatalogCollection, error) + DoCreate func(opts *rancherClient.ProjectCatalog) (*rancherClient.ProjectCatalog, error) + DoUpdate func(existing *rancherClient.ProjectCatalog, updates interface{}) (*rancherClient.ProjectCatalog, error) + DoReplace func(existing *rancherClient.ProjectCatalog) (*rancherClient.ProjectCatalog, error) + DoByID func(id string) (*rancherClient.ProjectCatalog, error) + DoDelete func(container *rancherClient.ProjectCatalog) error + DoActionRefresh func(container *rancherClient.ProjectCatalog) error + DoCollectionActionRefresh func(container *rancherClient.ProjectCatalogCollection) error +} + +// List implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.List(...) +func (stub ProjectCatalogOperationsStub) List(opts *types.ListOpts) (*rancherClient.ProjectCatalogCollection, error) { + return stub.DoList(opts) +} + +// Create implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.Create(...) +func (stub ProjectCatalogOperationsStub) Create(opts *rancherClient.ProjectCatalog) (*rancherClient.ProjectCatalog, error) { + return stub.DoCreate(opts) +} + +// Update implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.Update(...) +func (stub ProjectCatalogOperationsStub) Update(existing *rancherClient.ProjectCatalog, updates interface{}) (*rancherClient.ProjectCatalog, error) { + return stub.DoUpdate(existing, updates) +} + +// Replace implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.Replace(...) +func (stub ProjectCatalogOperationsStub) Replace(existing *rancherClient.ProjectCatalog) (*rancherClient.ProjectCatalog, error) { + return stub.DoReplace(existing) +} + +// ByID implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.ByID(...) +func (stub ProjectCatalogOperationsStub) ByID(id string) (*rancherClient.ProjectCatalog, error) { + return stub.DoByID(id) +} + +// Delete implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.Delete(...) +func (stub ProjectCatalogOperationsStub) Delete(container *rancherClient.ProjectCatalog) error { + return stub.DoDelete(container) +} + +// ActionRefresh implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.ActionRefresh(...) +func (stub ProjectCatalogOperationsStub) ActionRefresh(resource *rancherClient.ProjectCatalog) error { + return stub.DoActionRefresh(resource) +} + +// CollectionActionRefresh implements github.com/rancher/types/client/project/v3/ProjectCatalogOperations.CollectionActionRefresh(...) +func (stub ProjectCatalogOperationsStub) CollectionActionRefresh(resource *rancherClient.ProjectCatalogCollection) error { + return stub.DoCollectionActionRefresh(resource) +} diff --git a/internal/pkg/rancher/stubs/rancher_catalog_operations_stub.go b/internal/pkg/rancher/stubs/rancher_catalog_operations_stub.go new file mode 100644 index 0000000..7edfe59 --- /dev/null +++ b/internal/pkg/rancher/stubs/rancher_catalog_operations_stub.go @@ -0,0 +1,115 @@ +// Copyright © 2019 Bitgrip +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stubs + +import ( + "testing" + + "github.com/bitgrip/cattlectl/internal/pkg/assert" + "github.com/rancher/norman/types" + rancherClient "github.com/rancher/types/client/management/v3" +) + +// CreateRancherCatalogOperationsStub creates a stub of github.com/rancher/types/client/project/v3/RancherCatalogOperations +func CreateRancherCatalogOperationsStub(tb testing.TB) *RancherCatalogOperationsStub { + return &RancherCatalogOperationsStub{ + tb: tb, + DoList: func(opts *types.ListOpts) (*rancherClient.CatalogCollection, error) { + assert.FailInStub(tb, 2, "Unexpected call of List") + return nil, nil + }, + DoCreate: func(opts *rancherClient.Catalog) (*rancherClient.Catalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Create") + return nil, nil + }, + DoUpdate: func(existing *rancherClient.Catalog, updates interface{}) (*rancherClient.Catalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Update") + return nil, nil + }, + DoReplace: func(existing *rancherClient.Catalog) (*rancherClient.Catalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of Replace") + return nil, nil + }, + DoByID: func(id string) (*rancherClient.Catalog, error) { + assert.FailInStub(tb, 2, "Unexpected call of ByID") + return nil, nil + }, + DoDelete: func(container *rancherClient.Catalog) error { + assert.FailInStub(tb, 2, "Unexpected call of Delete") + return nil + }, + DoActionRefresh: func(container *rancherClient.Catalog) error { + assert.FailInStub(tb, 2, "Unexpected call of ActionRefresh") + return nil + }, + DoCollectionActionRefresh: func(container *rancherClient.CatalogCollection) error { + assert.FailInStub(tb, 2, "Unexpected call of CollectionActionRefresh") + return nil + }, + } +} + +// RancherCatalogOperationsStub structure to hold callbacks used to stub github.com/rancher/types/client/project/v3/RancherCatalogOperations +type RancherCatalogOperationsStub struct { + tb testing.TB + DoList func(opts *types.ListOpts) (*rancherClient.CatalogCollection, error) + DoCreate func(opts *rancherClient.Catalog) (*rancherClient.Catalog, error) + DoUpdate func(existing *rancherClient.Catalog, updates interface{}) (*rancherClient.Catalog, error) + DoReplace func(existing *rancherClient.Catalog) (*rancherClient.Catalog, error) + DoByID func(id string) (*rancherClient.Catalog, error) + DoDelete func(container *rancherClient.Catalog) error + DoActionRefresh func(container *rancherClient.Catalog) error + DoCollectionActionRefresh func(container *rancherClient.CatalogCollection) error +} + +// List implements github.com/rancher/types/client/project/v3/RancherCatalogOperations.List(...) +func (stub RancherCatalogOperationsStub) List(opts *types.ListOpts) (*rancherClient.CatalogCollection, error) { + return stub.DoList(opts) +} + +// Create implements github.com/rancher/types/client/project/v3/RancherCatalogOperations.Create(...) +func (stub RancherCatalogOperationsStub) Create(opts *rancherClient.Catalog) (*rancherClient.Catalog, error) { + return stub.DoCreate(opts) +} + +// Update implements github.com/rancher/types/client/project/v3/RancherCatalogOperations.Update(...) +func (stub RancherCatalogOperationsStub) Update(existing *rancherClient.Catalog, updates interface{}) (*rancherClient.Catalog, error) { + return stub.DoUpdate(existing, updates) +} + +// Replace implements github.com/rancher/types/client/project/v3/RancherCatalogOperations.Replace(...) +func (stub RancherCatalogOperationsStub) Replace(existing *rancherClient.Catalog) (*rancherClient.Catalog, error) { + return stub.DoReplace(existing) +} + +// ByID implements github.com/rancher/types/client/project/v3/RancherCatalogOperations.ByID(...) +func (stub RancherCatalogOperationsStub) ByID(id string) (*rancherClient.Catalog, error) { + return stub.DoByID(id) +} + +// Delete implements github.com/rancher/types/client/project/v3/RancherCatalogOperations.Delete(...) +func (stub RancherCatalogOperationsStub) Delete(container *rancherClient.Catalog) error { + return stub.DoDelete(container) +} + +// ActionRefresh implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.ActionRefresh(...) +func (stub RancherCatalogOperationsStub) ActionRefresh(resource *rancherClient.Catalog) error { + return stub.DoActionRefresh(resource) +} + +// CollectionActionRefresh implements github.com/rancher/types/client/project/v3/ClusterCatalogOperations.CollectionActionRefresh(...) +func (stub RancherCatalogOperationsStub) CollectionActionRefresh(resource *rancherClient.CatalogCollection) error { + return stub.DoCollectionActionRefresh(resource) +} diff --git a/sample/cluster-with-catalog/cluster.yaml b/sample/cluster-with-catalog/cluster.yaml new file mode 100644 index 0000000..77c1462 --- /dev/null +++ b/sample/cluster-with-catalog/cluster.yaml @@ -0,0 +1,7 @@ +--- +api_version: v1.0 +kind: Cluster +catalogs: + - name: test-cluster-catalog + url: https://charts.bitnami.com/bitnami + branch: "{{ .catalog_branch }}" \ No newline at end of file diff --git a/sample/cluster-with-catalog/values1.yaml b/sample/cluster-with-catalog/values1.yaml new file mode 100644 index 0000000..1d631ce --- /dev/null +++ b/sample/cluster-with-catalog/values1.yaml @@ -0,0 +1,2 @@ +project_name: test-project +catalog_branch: master diff --git a/sample/cluster-with-catalog/values2.yaml b/sample/cluster-with-catalog/values2.yaml new file mode 100644 index 0000000..d34d565 --- /dev/null +++ b/sample/cluster-with-catalog/values2.yaml @@ -0,0 +1,2 @@ +project_name: test-project +catalog_branch: develop diff --git a/sample/project-with-catalog/project.yaml b/sample/project-with-catalog/project.yaml new file mode 100644 index 0000000..b6e566e --- /dev/null +++ b/sample/project-with-catalog/project.yaml @@ -0,0 +1,9 @@ +--- +api_version: v1.0 +kind: Project +metadata: + name: "{{ .project_name }}" +catalogs: + - name: test-project-catalog + url: https://charts.bitnami.com/bitnami + branch: "{{ .catalog_branch }}" \ No newline at end of file diff --git a/sample/project-with-catalog/values1.yaml b/sample/project-with-catalog/values1.yaml new file mode 100644 index 0000000..1d631ce --- /dev/null +++ b/sample/project-with-catalog/values1.yaml @@ -0,0 +1,2 @@ +project_name: test-project +catalog_branch: master diff --git a/sample/project-with-catalog/values2.yaml b/sample/project-with-catalog/values2.yaml new file mode 100644 index 0000000..d34d565 --- /dev/null +++ b/sample/project-with-catalog/values2.yaml @@ -0,0 +1,2 @@ +project_name: test-project +catalog_branch: develop diff --git a/sample/rancher-with-catalog/rancher.yaml b/sample/rancher-with-catalog/rancher.yaml new file mode 100644 index 0000000..55a1d4e --- /dev/null +++ b/sample/rancher-with-catalog/rancher.yaml @@ -0,0 +1,7 @@ +--- +api_version: v1.0 +kind: Rancher +catalogs: + - name: test-rancher-catalog + url: https://charts.bitnami.com/bitnami + branch: "{{ .catalog_branch }}" \ No newline at end of file diff --git a/sample/rancher-with-catalog/values1.yaml b/sample/rancher-with-catalog/values1.yaml new file mode 100644 index 0000000..1d631ce --- /dev/null +++ b/sample/rancher-with-catalog/values1.yaml @@ -0,0 +1,2 @@ +project_name: test-project +catalog_branch: master diff --git a/sample/rancher-with-catalog/values2.yaml b/sample/rancher-with-catalog/values2.yaml new file mode 100644 index 0000000..d34d565 --- /dev/null +++ b/sample/rancher-with-catalog/values2.yaml @@ -0,0 +1,2 @@ +project_name: test-project +catalog_branch: develop