diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c4e3b240..8e2f8134c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add Helm revision number to chart CR status. +- Extend Chart CR documentation. diff --git a/docs/cr/application.giantswarm.io_v1alpha1_chart.yaml b/docs/cr/application.giantswarm.io_v1alpha1_chart.yaml new file mode 100644 index 000000000..7215616bc --- /dev/null +++ b/docs/cr/application.giantswarm.io_v1alpha1_chart.yaml @@ -0,0 +1,21 @@ +apiVersion: application.giantswarm.io/v1alpha1 +kind: Chart +metadata: + annotations: + giantswarm.io/docs: https://pkg.go.dev/github.com/giantswarm/apiextensions/pkg/apis/application/v1alpha1?tab=doc#Chart + creationTimestamp: null + name: prometheus +spec: + config: + configMap: + name: f2def-chart-values + namespace: f2def + resourceVersion: "" + secret: + name: f2def-chart-values + namespace: f2def + resourceVersion: "" + name: prometheus + namespace: monitoring + tarballURL: prometheus-1.0.1.tgz + version: 1.0.1 diff --git a/docs/crd/application.giantswarm.io_chart.yaml b/docs/crd/application.giantswarm.io_chart.yaml new file mode 100644 index 000000000..d170a2a44 --- /dev/null +++ b/docs/crd/application.giantswarm.io_chart.yaml @@ -0,0 +1,94 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: charts.application.giantswarm.io +spec: + group: application.giantswarm.io + names: + kind: Chart + plural: charts + singular: chart + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: | + Defines a Chart resource, which represents an application version running on the cluster. + This resource is created and managed by chart-operator running in each tenant cluster. + properties: + spec: + properties: + config: + description: "Defines the aggregated configuration values for the application + chart. It is \ncreated by app-operator in the tenant cluster to be + used as values file by \nchart operator during the helm installation + process.\nproccess. \n" + properties: + configMap: + description: "Defines a reference to a ConfigMap where is the aggregated + configuration values \nfrom App Catalog, Cluster and User that + will be used as values file in the helm\ninstallation or upgrade + process.\n" + properties: + name: + description: | + Name of the ConfigMap resource. + type: string + namespace: + description: | + Namespace holding the ConfigMap resource. + type: string + resourceVersion: + type: string + required: + - name + - namespace + type: object + secret: + description: | + Defines a reference to a Secret where is the aggregated configuration values from App Catalog, Cluster and User that will be used as values file in the helm + installation or upgrade process. + properties: + name: + description: | + Name of the Secret resource. + type: string + namespace: + description: | + Namespace holding the Secret resource. + type: string + resourceVersion: + type: string + required: + - name + - namespace + type: object + type: object + name: + description: | + Name of this application Chart. + type: string + namespace: + description: | + Kubernetes namespace in which to install the workloads defined by this App Chart in + the current cluster. + type: string + tarballURL: + description: "URL of the application Chart to be deployed. The chart + package must exist in the \nApp Catalog storage.\n" + format: uri + type: string + version: + description: | + Version of the application Chart to be deployed. + type: string + required: + - name + - namespace + - tarballURL + - version + type: object + type: object + version: v1alpha1 diff --git a/pkg/apis/application/v1alpha1/chart_types.go b/pkg/apis/application/v1alpha1/chart_types.go index e70ce4aa9..5515189f4 100644 --- a/pkg/apis/application/v1alpha1/chart_types.go +++ b/pkg/apis/application/v1alpha1/chart_types.go @@ -7,7 +7,8 @@ import ( ) const ( - kindChart = "Chart" + kindChart = "Chart" + chartDocumentationLink = "https://pkg.go.dev/github.com/giantswarm/apiextensions/pkg/apis/application/v1alpha1?tab=doc#Chart" ) const chartCRDYAML = ` @@ -27,42 +28,75 @@ spec: status: {} validation: openAPIV3Schema: + description: | + Defines a Chart resource, which represents an application version running on the cluster. + This resource is created and managed by chart-operator running in each tenant cluster. type: object properties: spec: type: object properties: name: + description: | + Name of this application Chart. type: string namespace: + description: | + Kubernetes namespace in which to install the workloads defined by this App Chart in + the current cluster. type: string config: + description: | + Defines the aggregated configuration values for the application chart. It is + created by app-operator in the tenant cluster to be used as values file by + chart operator during the helm installation process. + proccess. type: object properties: configMap: + description: | + Defines a reference to a ConfigMap where is the aggregated configuration values + from App Catalog, Cluster and User that will be used as values file in the helm + installation or upgrade process. type: object properties: name: + description: | + Name of the ConfigMap resource. type: string namespace: + description: | + Namespace holding the ConfigMap resource. type: string resourceVersion: type: string required: ["name", "namespace"] secret: + description: | + Defines a reference to a Secret where is the aggregated configuration values from App Catalog, Cluster and User that will be used as values file in the helm + installation or upgrade process. type: object properties: name: + description: | + Name of the Secret resource. type: string namespace: + description: | + Namespace holding the Secret resource. type: string resourceVersion: type: string required: ["name", "namespace"] tarballURL: + description: | + URL of the application Chart to be deployed. The chart package must exist in the + App Catalog storage. type: string format: uri version: + description: | + Version of the application Chart to be deployed. type: string required: ["name", "namespace", "tarballURL", "version"] ` @@ -103,6 +137,18 @@ func NewChartTypeMeta() metav1.TypeMeta { } } +// NewChartCR returns an Chart Custom Resource. +func NewChartCR() *Chart { + return &Chart{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + crDocsAnnotation: chartDocumentationLink, + }, + }, + TypeMeta: NewChartTypeMeta(), + } +} + // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/application/v1alpha1/chart_types_test.go b/pkg/apis/application/v1alpha1/chart_types_test.go index a8824da31..b68030f7e 100644 --- a/pkg/apis/application/v1alpha1/chart_types_test.go +++ b/pkg/apis/application/v1alpha1/chart_types_test.go @@ -1,6 +1,17 @@ package v1alpha1 -import "testing" +import ( + "bytes" + "fmt" + "io/ioutil" + "path/filepath" + "regexp" + "testing" + + "github.com/google/go-cmp/cmp" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/yaml" +) func Test_NewChartCRD(t *testing.T) { crd := NewChartCRD() @@ -8,3 +19,78 @@ func Test_NewChartCRD(t *testing.T) { t.Error("Chart CRD was nil.") } } + +func Test_GenerateChartYAML(t *testing.T) { + testCases := []struct { + category string + name string + resource runtime.Object + }{ + { + category: "crd", + name: fmt.Sprintf("%s_chart.yaml", group), + resource: NewChartCRD(), + }, + { + category: "cr", + name: fmt.Sprintf("%s_%s_chart.yaml", group, version), + resource: newChartExampleCR(), + }, + } + + docs := filepath.Join(root, "..", "..", "..", "..", "docs") + for i, tc := range testCases { + t.Run(fmt.Sprintf("case %d: generates %s successfully", i, tc.name), func(t *testing.T) { + rendered, err := yaml.Marshal(tc.resource) + if err != nil { + t.Fatal(err) + } + directory := filepath.Join(docs, tc.category) + path := filepath.Join(directory, tc.name) + + // We don't want a status in the docs YAML for the CR and CRD so that they work with `kubectl create -f .yaml`. + // This just strips off the top level `status:` and everything following. + statusRegex := regexp.MustCompile(`(?ms)^status:.*$`) + rendered = statusRegex.ReplaceAll(rendered, []byte("")) + + if *update { + err := ioutil.WriteFile(path, rendered, 0644) + if err != nil { + t.Fatal(err) + } + } + goldenFile, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(rendered, goldenFile) { + t.Fatalf("\n\n%s\n", cmp.Diff(string(goldenFile), string(rendered))) + } + }) + } +} + +func newChartExampleCR() *Chart { + cr := NewChartCR() + + cr.Name = "prometheus" + cr.Spec = ChartSpec{ + Name: "prometheus", + Namespace: "monitoring", + Config: ChartSpecConfig{ + ConfigMap: ChartSpecConfigConfigMap{ + Name: "f2def-chart-values", + Namespace: "f2def", + }, + Secret: ChartSpecConfigSecret{ + Name: "f2def-chart-values", + Namespace: "f2def", + }, + }, + TarballURL: "prometheus-1.0.1.tgz", + Version: "1.0.1", + } + + return cr +}