diff --git a/manifests/templates/deployment-replication/deployment-replication.yaml b/manifests/templates/deployment-replication/deployment-replication.yaml index 7b5301127..fc8bc7ec4 100644 --- a/manifests/templates/deployment-replication/deployment-replication.yaml +++ b/manifests/templates/deployment-replication/deployment-replication.yaml @@ -1,3 +1,4 @@ +{{ .DeploymentReplication.FilterStart }} apiVersion: extensions/v1beta1 kind: Deployment @@ -14,6 +15,7 @@ spec: name: {{ .DeploymentReplication.OperatorDeploymentName }} app: arango-deployment-replication-operator spec: + serviceAccountName: {{ .DeploymentReplication.Operator.ServiceAccountName }} containers: - name: operator imagePullPolicy: {{ .ImagePullPolicy }} @@ -59,3 +61,5 @@ spec: operator: "Exists" effect: "NoExecute" tolerationSeconds: 5 + +{{ .DeploymentReplication.FilterEnd }} diff --git a/manifests/templates/deployment-replication/rbac.yaml b/manifests/templates/deployment-replication/rbac.yaml index 5c7671ed6..3e62b13ad 100644 --- a/manifests/templates/deployment-replication/rbac.yaml +++ b/manifests/templates/deployment-replication/rbac.yaml @@ -1,4 +1,6 @@ -{{- if .RBAC -}} +{{ .DeploymentReplication.FilterStart }} +{{ .RBACFilterStart }} + ## Cluster role granting access to ArangoDeploymentReplication resources. apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole @@ -72,4 +74,5 @@ subjects: name: {{ .DeploymentReplication.Operator.ServiceAccountName }} namespace: {{ .DeploymentReplication.Operator.Namespace }} -{{- end -}} +{{ .RBACFilterEnd }} +{{ .DeploymentReplication.FilterEnd }} diff --git a/manifests/templates/deployment-replication/service.yaml b/manifests/templates/deployment-replication/service.yaml index 2f946ad43..301fe9bee 100644 --- a/manifests/templates/deployment-replication/service.yaml +++ b/manifests/templates/deployment-replication/service.yaml @@ -1,3 +1,5 @@ +{{ .DeploymentReplication.FilterStart }} + apiVersion: v1 kind: Service metadata: @@ -17,3 +19,5 @@ spec: app: arango-deployment-replication-operator role: leader type: {{ .DeploymentReplication.Operator.ServiceType }} + +{{ .DeploymentReplication.FilterEnd }} diff --git a/manifests/templates/deployment/deployment.yaml b/manifests/templates/deployment/deployment.yaml index 01b6a14a6..808ed87cd 100644 --- a/manifests/templates/deployment/deployment.yaml +++ b/manifests/templates/deployment/deployment.yaml @@ -1,3 +1,4 @@ +{{ .Deployment.FilterStart }} apiVersion: extensions/v1beta1 kind: Deployment @@ -14,6 +15,7 @@ spec: name: {{ .Deployment.OperatorDeploymentName }} app: arango-deployment-operator spec: + serviceAccountName: {{ .Deployment.Operator.ServiceAccountName }} containers: - name: operator imagePullPolicy: {{ .ImagePullPolicy }} @@ -60,3 +62,5 @@ spec: operator: "Exists" effect: "NoExecute" tolerationSeconds: 5 + +{{ .Deployment.FilterEnd }} diff --git a/manifests/templates/deployment/rbac.yaml b/manifests/templates/deployment/rbac.yaml index 208b34ac4..6b0c662ef 100644 --- a/manifests/templates/deployment/rbac.yaml +++ b/manifests/templates/deployment/rbac.yaml @@ -1,4 +1,6 @@ -{{- if .RBAC -}} +{{ .Deployment.FilterStart }} +{{ .RBACFilterStart }} + ## Cluster role granting access to ArangoDeployment resources. apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole @@ -72,4 +74,5 @@ subjects: name: {{ .Deployment.Operator.ServiceAccountName }} namespace: {{ .Deployment.Operator.Namespace }} -{{- end -}} +{{ .RBACFilterEnd }} +{{ .Deployment.FilterEnd }} diff --git a/manifests/templates/deployment/service.yaml b/manifests/templates/deployment/service.yaml index e7cc83a68..089596562 100644 --- a/manifests/templates/deployment/service.yaml +++ b/manifests/templates/deployment/service.yaml @@ -1,3 +1,5 @@ +{{ .Deployment.FilterStart }} + apiVersion: v1 kind: Service metadata: @@ -17,3 +19,5 @@ spec: app: arango-deployment-operator role: leader type: {{ .Deployment.Operator.ServiceType }} + +{{ .Deployment.FilterEnd }} diff --git a/manifests/templates/storage/deployment.yaml b/manifests/templates/storage/deployment.yaml index f6ffbf51b..1ec6a5f9c 100644 --- a/manifests/templates/storage/deployment.yaml +++ b/manifests/templates/storage/deployment.yaml @@ -1,3 +1,5 @@ +{{ .Storage.FilterStart }} + ## Service accounts apiVersion: v1 kind: ServiceAccount @@ -68,3 +70,5 @@ spec: operator: "Exists" effect: "NoExecute" tolerationSeconds: 5 + +{{ .Storage.FilterEnd }} diff --git a/manifests/templates/storage/rbac.yaml b/manifests/templates/storage/rbac.yaml index 99a447150..6126852f8 100644 --- a/manifests/templates/storage/rbac.yaml +++ b/manifests/templates/storage/rbac.yaml @@ -1,5 +1,6 @@ +{{ .Storage.FilterStart }} +{{ .RBACFilterStart }} -{{- if .RBAC -}} ## Cluster role granting access to ArangoLocalStorage resources. apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole @@ -81,4 +82,6 @@ subjects: - kind: ServiceAccount name: {{ .Storage.Operator.ServiceAccountName }} namespace: {{ .Storage.Operator.Namespace }} -{{- end -}} + +{{ .RBACFilterEnd }} +{{ .Storage.FilterEnd }} diff --git a/manifests/templates/storage/service.yaml b/manifests/templates/storage/service.yaml index 2fb9c2cde..c40163abb 100644 --- a/manifests/templates/storage/service.yaml +++ b/manifests/templates/storage/service.yaml @@ -1,3 +1,5 @@ +{{ .Storage.FilterStart }} + apiVersion: v1 kind: Service metadata: @@ -17,3 +19,5 @@ spec: app: arango-storage-operator role: leader type: {{ .Storage.Operator.ServiceType }} + +{{ .Storage.FilterEnd }} diff --git a/manifests/templates/test/rbac.yaml b/manifests/templates/test/rbac.yaml index 16848c872..973a0d725 100644 --- a/manifests/templates/test/rbac.yaml +++ b/manifests/templates/test/rbac.yaml @@ -1,4 +1,4 @@ -{{- if .RBAC -}} +{{ .RBACFilterStart }} ## Cluster role granting access to resources needed by the integration tests. apiVersion: rbac.authorization.k8s.io/v1beta1 @@ -34,4 +34,4 @@ subjects: name: {{ .Test.ServiceAccountName }} namespace: {{ .Test.Namespace }} -{{- end -}} +{{ .RBACFilterEnd }} diff --git a/tools/manifests/manifest_builder.go b/tools/manifests/manifest_builder.go index 1be5ab740..b6e3afe88 100644 --- a/tools/manifests/manifest_builder.go +++ b/tools/manifests/manifest_builder.go @@ -30,6 +30,7 @@ import ( "os" "os/exec" "path/filepath" + "strconv" "strings" "text/template" @@ -51,26 +52,102 @@ var ( RBAC bool AllowChaos bool } - deploymentTemplateNames = []string{ - "rbac.yaml", - "deployment.yaml", - "service.yaml", + deploymentTemplateNames = []Template{ + Template{Name: "rbac.yaml", Predicate: hasRBAC}, + Template{Name: "deployment.yaml"}, + Template{Name: "service.yaml"}, } - deploymentReplicationTemplateNames = []string{ - "rbac.yaml", - "deployment-replication.yaml", - "service.yaml", + deploymentReplicationTemplateNames = []Template{ + Template{Name: "rbac.yaml", Predicate: hasRBAC}, + Template{Name: "deployment-replication.yaml"}, + Template{Name: "service.yaml"}, } - storageTemplateNames = []string{ - "rbac.yaml", - "deployment.yaml", - "service.yaml", + storageTemplateNames = []Template{ + Template{Name: "rbac.yaml", Predicate: hasRBAC}, + Template{Name: "deployment.yaml"}, + Template{Name: "service.yaml"}, } - testTemplateNames = []string{ - "rbac.yaml", + testTemplateNames = []Template{ + Template{Name: "rbac.yaml", Predicate: func(o TemplateOptions, isHelm bool) bool { return o.RBAC && !isHelm }}, } ) +type Template struct { + Name string + Predicate func(o TemplateOptions, isHelm bool) bool +} + +type TemplateGroup struct { + ChartName string + Templates []Template +} + +func hasRBAC(o TemplateOptions, isHelm bool) bool { + return o.RBAC || isHelm +} + +var ( + tmplFuncs = template.FuncMap{ + "quote": func(x string) string { return strconv.Quote(x) }, + } +) + +type ( + chartTemplates map[string]string +) + +const ( + kubeArangoDBChartTemplate = ` +apiVersion: v1 +name: kube-arangodb +version: "{{ .Version }}" +description: | + Kube-ArangoDB is a set of operators to easily deploy ArangoDB deployments on Kubernetes +home: https://arangodb.com +` + kubeArangoDBStorageChartTemplate = ` +apiVersion: v1 +name: kube-arangodb-storage +version: "{{ .Version }}" +description: | + Kube-ArangoDB-Storage is a cluster-wide operator used to provision PersistentVolumes on disks attached locally to Nodes +home: https://arangodb.com +` + kubeArangoDBValuesTemplate = ` +Image: {{ .Image | quote }} +ImagePullPolicy: {{ .ImagePullPolicy | quote }} +RBAC: + Create: {{ .RBAC }} +Deployment: + Create: {{ .Deployment.Create }} + User: + ServiceAccountName: {{ .Deployment.User.ServiceAccountName | quote }} + Operator: + ServiceAccountName: {{ .Deployment.Operator.ServiceAccountName | quote }} + ServiceType: {{ .Deployment.Operator.ServiceType | quote }} + AllowChaos: {{ .Deployment.AllowChaos }} +DeploymentReplication: + Create: {{ .DeploymentReplication.Create }} + User: + ServiceAccountName: {{ .DeploymentReplication.User.ServiceAccountName | quote }} + Operator: + ServiceAccountName: {{ .DeploymentReplication.Operator.ServiceAccountName | quote }} + ServiceType: {{ .DeploymentReplication.Operator.ServiceType | quote }} +` + kubeArangoDBStorageValuesTemplate = ` +Image: {{ .Image | quote }} +ImagePullPolicy: {{ .ImagePullPolicy | quote }} +RBAC: + Create: {{ .RBAC }} +Storage: + User: + ServiceAccountName: {{ .Storage.User.ServiceAccountName | quote }} + Operator: + ServiceAccountName: {{ .Storage.Operator.ServiceAccountName | quote }} + ServiceType: {{ .Storage.Operator.ServiceType | quote }} +` +) + func init() { pflag.StringVar(&options.OutputSuffix, "output-suffix", "", "Suffix of the generated manifest files") pflag.StringVar(&options.TemplatesDir, "templates-dir", "manifests/templates", "Directory containing manifest templates") @@ -88,9 +165,12 @@ func init() { } type TemplateOptions struct { + Version string Image string ImagePullPolicy string RBAC bool + RBACFilterStart string + RBACFilterEnd string Deployment ResourceOptions DeploymentReplication ResourceOptions Storage ResourceOptions @@ -106,10 +186,13 @@ type CommonOptions struct { } type ResourceOptions struct { + Create string + FilterStart string + FilterEnd string User CommonOptions Operator CommonOptions OperatorDeploymentName string - AllowChaos bool + AllowChaos string } func main() { @@ -138,19 +221,27 @@ func main() { } // Prepare templates to include - templateNameSet := map[string][]string{ - "deployment": deploymentTemplateNames, - "deployment-replication": deploymentReplicationTemplateNames, - "storage": storageTemplateNames, - "test": testTemplateNames, + templateInfoSet := map[string]TemplateGroup{ + "deployment": TemplateGroup{ChartName: "kube-arangodb", Templates: deploymentTemplateNames}, + "deployment-replication": TemplateGroup{ChartName: "kube-arangodb", Templates: deploymentReplicationTemplateNames}, + "storage": TemplateGroup{ChartName: "kube-arangodb-storage", Templates: storageTemplateNames}, + "test": TemplateGroup{ChartName: "", Templates: testTemplateNames}, + } + + // Read VERSION + version, err := ioutil.ReadFile("VERSION") + if err != nil { + log.Fatalf("Failed to read VERSION file: %v", err) } // Process templates templateOptions := TemplateOptions{ + Version: strings.TrimSpace(string(version)), Image: options.Image, ImagePullPolicy: options.ImagePullPolicy, RBAC: options.RBAC, Deployment: ResourceOptions{ + Create: "true", User: CommonOptions{ Namespace: options.Namespace, RoleName: "arango-deployments", @@ -165,9 +256,10 @@ func main() { ServiceType: "ClusterIP", }, OperatorDeploymentName: "arango-deployment-operator", - AllowChaos: options.AllowChaos, + AllowChaos: strconv.FormatBool(options.AllowChaos), }, DeploymentReplication: ResourceOptions{ + Create: "true", User: CommonOptions{ Namespace: options.Namespace, RoleName: "arango-deployment-replications", @@ -184,6 +276,7 @@ func main() { OperatorDeploymentName: "arango-deployment-replication-operator", }, Storage: ResourceOptions{ + Create: "true", User: CommonOptions{ Namespace: options.Namespace, RoleName: "arango-storages", @@ -206,32 +299,174 @@ func main() { ServiceAccountName: "default", }, } - for group, templateNames := range templateNameSet { - output := &bytes.Buffer{} - for i, name := range templateNames { - t, err := template.New(name).ParseFiles(filepath.Join(options.TemplatesDir, group, name)) + chartTemplateOptions := TemplateOptions{ + Version: strings.TrimSpace(string(version)), + RBACFilterStart: "{{- if .Values.RBAC.Create }}", + RBACFilterEnd: "{{- end }}", + Image: "{{ .Values.Image }}", + ImagePullPolicy: "{{ .Values.ImagePullPolicy }}", + Deployment: ResourceOptions{ + Create: "{{ .Values.Deployment.Create }}", + FilterStart: "{{- if .Values.Deployment.Create }}", + FilterEnd: "{{- end }}", + User: CommonOptions{ + Namespace: "{{ .Release.Namespace }}", + RoleName: `{{ printf "%s-%s" .Release.Name "deployments" | trunc 63 | trimSuffix "-" }}`, + RoleBindingName: `{{ printf "%s-%s" .Release.Name "deployments" | trunc 63 | trimSuffix "-" }}`, + ServiceAccountName: "{{ .Values.Deployment.User.ServiceAccountName }}", + }, + Operator: CommonOptions{ + Namespace: "{{ .Release.Namespace }}", + RoleName: `{{ printf "%s-%s" .Release.Name "deployment-operator" | trunc 63 | trimSuffix "-" }}`, + RoleBindingName: `{{ printf "%s-%s" .Release.Name "deployment-operator" | trunc 63 | trimSuffix "-" }}`, + ServiceAccountName: "{{ .Values.Deployment.Operator.ServiceAccountName }}", + ServiceType: "{{ .Values.Deployment.Operator.ServiceType }}", + }, + OperatorDeploymentName: `{{ printf "%s-%s" .Release.Name "deployment-operator" | trunc 63 | trimSuffix "-" }}`, + AllowChaos: "{{ .Values.Deployment.AllowChaos }}", + }, + DeploymentReplication: ResourceOptions{ + Create: "{{ .Values.DeploymentReplication.Create }}", + FilterStart: "{{- if .Values.DeploymentReplication.Create }}", + FilterEnd: "{{- end }}", + User: CommonOptions{ + Namespace: "{{ .Release.Namespace }}", + RoleName: `{{ printf "%s-%s" .Release.Name "deployment-replications" | trunc 63 | trimSuffix "-" }}`, + RoleBindingName: `{{ printf "%s-%s" .Release.Name "deployment-replications" | trunc 63 | trimSuffix "-" }}`, + ServiceAccountName: "{{ .Values.DeploymentReplication.User.ServiceAccountName }}", + }, + Operator: CommonOptions{ + Namespace: "{{ .Release.Namespace }}", + RoleName: `{{ printf "%s-%s" .Release.Name "deployment-replication-operator" | trunc 63 | trimSuffix "-" }}`, + RoleBindingName: `{{ printf "%s-%s" .Release.Name "deployment-replication-operator" | trunc 63 | trimSuffix "-" }}`, + ServiceAccountName: "{{ .Values.DeploymentReplication.Operator.ServiceAccountName }}", + ServiceType: "{{ .Values.DeploymentReplication.Operator.ServiceType }}", + }, + OperatorDeploymentName: `{{ printf "%s-%s" .Release.Name "deployment-replication-operator" | trunc 63 | trimSuffix "-" }}`, + }, + Storage: ResourceOptions{ + Create: "{{ .Values.Storage.Create }}", + User: CommonOptions{ + Namespace: "{{ .Release.Namespace }}", + RoleName: `{{ printf "%s-%s" .Release.Name "storages" | trunc 63 | trimSuffix "-" }}`, + RoleBindingName: `{{ printf "%s-%s" .Release.Name "storages" | trunc 63 | trimSuffix "-" }}`, + ServiceAccountName: "{{ .Values.Storage.User.ServiceAccountName }}", + }, + Operator: CommonOptions{ + Namespace: "kube-system", + RoleName: `{{ printf "%s-%s" .Release.Name "storage-operator" | trunc 63 | trimSuffix "-" }}`, + RoleBindingName: `{{ printf "%s-%s" .Release.Name "storage-operator" | trunc 63 | trimSuffix "-" }}`, + ServiceAccountName: "{{ .Values.Storage.Operator.ServiceAccountName }}", + ServiceType: "{{ .Values.Storage.Operator.ServiceType }}", + }, + OperatorDeploymentName: `{{ printf "%s-%s" .Release.Name "storage-operator" | trunc 63 | trimSuffix "-" }}`, + }, + } + + for group, templateGroup := range templateInfoSet { + // Build standalone yaml file for this group + { + output := &bytes.Buffer{} + for i, tempInfo := range templateGroup.Templates { + if tempInfo.Predicate == nil || tempInfo.Predicate(templateOptions, false) { + name := tempInfo.Name + t, err := template.New(name).ParseFiles(filepath.Join(options.TemplatesDir, group, name)) + if err != nil { + log.Fatalf("Failed to parse template %s: %v", name, err) + } + if i > 0 { + output.WriteString("\n---\n\n") + } + output.WriteString(fmt.Sprintf("## %s/%s\n", group, name)) + t.Execute(output, templateOptions) + output.WriteString("\n") + } + } + + // Save output + if output.Len() > 0 { + outputDir, err := filepath.Abs("manifests") + if err != nil { + log.Fatalf("Failed to get absolute output dir: %v\n", err) + } + outputPath := filepath.Join(outputDir, "arango-"+group+options.OutputSuffix+".yaml") + if err := os.MkdirAll(outputDir, 0755); err != nil { + log.Fatalf("Failed to create output directory: %v\n", err) + } + if err := ioutil.WriteFile(outputPath, output.Bytes(), 0644); err != nil { + log.Fatalf("Failed to write output file: %v\n", err) + } + } + } + + // Build helm template file for this group + { + output := &bytes.Buffer{} + for i, tempInfo := range templateGroup.Templates { + if tempInfo.Predicate == nil || tempInfo.Predicate(chartTemplateOptions, true) { + name := tempInfo.Name + t, err := template.New(name).ParseFiles(filepath.Join(options.TemplatesDir, group, name)) + if err != nil { + log.Fatalf("Failed to parse template %s: %v", name, err) + } + if i > 0 { + output.WriteString("\n---\n\n") + } + output.WriteString(fmt.Sprintf("## %s/%s\n", group, name)) + t.Execute(output, chartTemplateOptions) + output.WriteString("\n") + } + } + + // Save output + if output.Len() > 0 { + outputDir, err := filepath.Abs(filepath.Join("bin", "charts", templateGroup.ChartName, "templates")) + if err != nil { + log.Fatalf("Failed to get absolute output dir: %v\n", err) + } + outputPath := filepath.Join(outputDir, group+".yaml") + if err := os.MkdirAll(outputDir, 0755); err != nil { + log.Fatalf("Failed to create output directory: %v\n", err) + } + if err := ioutil.WriteFile(outputPath, output.Bytes(), 0644); err != nil { + log.Fatalf("Failed to write output file: %v\n", err) + } + } + } + } + + // Build Chart files + chartTemplateGroups := map[string]chartTemplates{ + "kube-arangodb": chartTemplates{ + "Chart.yaml": kubeArangoDBChartTemplate, + "values.yaml": kubeArangoDBValuesTemplate, + }, + "kube-arangodb-storage": chartTemplates{ + "Chart.yaml": kubeArangoDBStorageChartTemplate, + "values.yaml": kubeArangoDBStorageValuesTemplate, + }, + } + for groupName, chartTemplates := range chartTemplateGroups { + for name, templateSource := range chartTemplates { + output := &bytes.Buffer{} + t, err := template.New(name).Funcs(tmplFuncs).Parse(templateSource) if err != nil { log.Fatalf("Failed to parse template %s: %v", name, err) } - if i > 0 { - output.WriteString("\n---\n\n") - } - output.WriteString(fmt.Sprintf("## %s/%s\n", group, name)) t.Execute(output, templateOptions) - output.WriteString("\n") - } - // Save output - outputDir, err := filepath.Abs("manifests") - if err != nil { - log.Fatalf("Failed to get absolute output dir: %v\n", err) - } - outputPath := filepath.Join(outputDir, "arango-"+group+options.OutputSuffix+".yaml") - if err := os.MkdirAll(outputDir, 0755); err != nil { - log.Fatalf("Failed to create output directory: %v\n", err) - } - if err := ioutil.WriteFile(outputPath, output.Bytes(), 0644); err != nil { - log.Fatalf("Failed to write output file: %v\n", err) + // Save output + outputDir, err := filepath.Abs(filepath.Join("bin", "charts", groupName)) + if err != nil { + log.Fatalf("Failed to get absolute output dir: %v\n", err) + } + outputPath := filepath.Join(outputDir, name) + if err := os.MkdirAll(outputDir, 0755); err != nil { + log.Fatalf("Failed to create output directory: %v\n", err) + } + if err := ioutil.WriteFile(outputPath, output.Bytes(), 0644); err != nil { + log.Fatalf("Failed to write output file: %v\n", err) + } } } }