diff --git a/grafana/templates/bin/_db-session-sync.py.tpl b/grafana/templates/bin/_db-session-sync.py.tpl new file mode 100644 index 000000000..739478b8a --- /dev/null +++ b/grafana/templates/bin/_db-session-sync.py.tpl @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +# Creates db and user for an OpenStack Service: +# Set ROOT_DB_CONNECTION and DB_CONNECTION environment variables to contain +# SQLAlchemy strings for the root connection to the database and the one you +# wish the service to use. Alternatively, you can use an ini formatted config +# at the location specified by OPENSTACK_CONFIG_FILE, and extract the string +# from the key OPENSTACK_CONFIG_DB_KEY, in the section specified by +# OPENSTACK_CONFIG_DB_SECTION. + +import os +import sys +import ConfigParser +import logging +from sqlalchemy import create_engine + +# Create logger, console handler and formatter +logger = logging.getLogger('OpenStack-Helm DB Init') +logger.setLevel(logging.DEBUG) +ch = logging.StreamHandler() +ch.setLevel(logging.DEBUG) +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + +# Set the formatter and add the handler +ch.setFormatter(formatter) +logger.addHandler(ch) + +# Get the connection string for the service db +if "DB_CONNECTION" in os.environ: + user_db_conn = os.environ['DB_CONNECTION'] + logger.info('Got config from DB_CONNECTION env var') +else: + logger.critical('Could not get db config, either from config file or env var') + sys.exit(1) + +# User DB engine +try: + user_engine = create_engine(user_db_conn) + # Get our user data out of the user_engine + database = user_engine.url.database + user = user_engine.url.username + password = user_engine.url.password + host = user_engine.url.host + port = user_engine.url.port + logger.info('Got user db config') +except: + logger.critical('Could not get user database config') + raise + +# Test connection +try: + connection = user_engine.connect() + connection.close() + logger.info("Tested connection to DB @ {0}:{1}/{2} as {3}".format( + host, port, database, user)) +except: + logger.critical('Could not connect to database as user') + raise + +# Create Table +try: + user_engine.execute('''CREATE TABLE IF NOT EXISTS `session` ( + `key`CHAR(16) NOT NULL, + `data` BLOB, + `expiry` INT(11) UNSIGNED NOT NULL, + PRIMARY KEY (`key`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8;''') + logger.info('Created table for session cache') +except: + logger.critical('Could not create table for session cache') + raise diff --git a/grafana/templates/configmap-bin.yaml b/grafana/templates/configmap-bin.yaml index e107bbbfe..b1a566c9d 100644 --- a/grafana/templates/configmap-bin.yaml +++ b/grafana/templates/configmap-bin.yaml @@ -22,6 +22,10 @@ kind: ConfigMap metadata: name: grafana-bin data: + db-init.py: | +{{- include "helm-toolkit.scripts.db_init" . | indent 4 }} + db-session-sync.py: | +{{ tuple "bin/_db-session-sync.py.tpl" . | include "helm-toolkit.utils.template" | indent 4 }} image-repo-sync.sh: |+ {{- include "helm-toolkit.scripts.image_repo_sync" . | indent 4 }} datasource.sh: | diff --git a/grafana/templates/configmap-etc.yaml b/grafana/templates/configmap-etc.yaml index db42d493e..74f699e1f 100644 --- a/grafana/templates/configmap-etc.yaml +++ b/grafana/templates/configmap-etc.yaml @@ -16,6 +16,19 @@ limitations under the License. {{- if .Values.manifests.configmap_etc }} {{- $envAll := . }} + +{{- if and (empty .Values.conf.grafana.database.url) (not (eq .Values.conf.grafana.database.type "sqlite3") ) -}} +{{- tuple "oslo_db" "internal" "user" "mysql" . | include "helm-toolkit.endpoints.authenticated_endpoint_uri_lookup" | replace "mysql+pymysql://" "mysql://" | set .Values.conf.grafana.database "url" | quote | trunc 0 -}} +{{- end -}} + +{{- if empty .Values.conf.grafana.session.provider_config -}} +{{- $user := .Values.endpoints.oslo_db_session.auth.user.username }} +{{- $pass := .Values.endpoints.oslo_db_session.auth.user.password }} +{{- $host_port := tuple "oslo_db_session" "internal" "mysql" . | include "helm-toolkit.endpoints.host_and_port_endpoint_uri_lookup" }} +{{- $path := .Values.endpoints.oslo_db_session.path }} +{{- printf "%s:%s%s(%s)%s" $user $pass "@tcp" $host_port $path | set .Values.conf.grafana.session "provider_config" | quote | trunc 0 -}} +{{- end -}} + --- apiVersion: v1 kind: ConfigMap diff --git a/grafana/templates/deployment.yaml b/grafana/templates/deployment.yaml index 2551856a8..c3c67840b 100644 --- a/grafana/templates/deployment.yaml +++ b/grafana/templates/deployment.yaml @@ -43,6 +43,8 @@ spec: configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }} spec: serviceAccountName: {{ $serviceAccountName }} + nodeSelector: + {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }} initContainers: {{ tuple $envAll .Values.pod_dependency list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }} containers: diff --git a/grafana/templates/ingress-grafana.yaml b/grafana/templates/ingress-grafana.yaml index 43d6a6216..55c0d2fff 100644 --- a/grafana/templates/ingress-grafana.yaml +++ b/grafana/templates/ingress-grafana.yaml @@ -30,9 +30,7 @@ kind: Ingress metadata: name: {{ $ingressName }} annotations: - kubernetes.io/ingress.class: "nginx" - ingress.kubernetes.io/rewrite-target: / - ingress.kubernetes.io/proxy-body-size: {{ .Values.network.grafana.ingress.proxy_body_size }} +{{ toYaml .Values.network.grafana.ingress.annotations | indent 4 }} spec: rules: {{ if ne $hostNameNamespaced $hostNameFull }} diff --git a/grafana/templates/job-db-init-session.yaml b/grafana/templates/job-db-init-session.yaml new file mode 100644 index 000000000..ee80903a2 --- /dev/null +++ b/grafana/templates/job-db-init-session.yaml @@ -0,0 +1,67 @@ +{{/* +Copyright 2017 The Openstack-Helm Authors. + +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. +*/}} + +{{- if .Values.manifests.job_db_init_session }} +{{- $envAll := . }} +{{- $dependencies := .Values.dependencies.db_init_session }} + +{{- $serviceAccountName := "grafana-db-init-session" }} +{{ tuple $envAll $dependencies $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: grafana-db-init-session +spec: + template: + metadata: + labels: +{{ tuple $envAll "grafana" "db-init" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }} + spec: + serviceAccountName: {{ $serviceAccountName }} + restartPolicy: OnFailure + nodeSelector: + {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }} + initContainers: +{{ tuple $envAll $dependencies list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }} + containers: + - name: grafana-db-init-session +{{ tuple $envAll "db_init" | include "helm-toolkit.snippets.image" | indent 10 }} +{{ tuple $envAll $envAll.Values.pod.resources.jobs.db_init_session | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }} + env: + - name: ROOT_DB_CONNECTION + valueFrom: + secretKeyRef: + name: {{ .Values.secrets.oslo_db_session.admin }} + key: DB_CONNECTION + - name: DB_CONNECTION + valueFrom: + secretKeyRef: + name: {{ .Values.secrets.oslo_db_session.user }} + key: DB_CONNECTION + command: + - /tmp/db-init.py + volumeMounts: + - name: grafana-bin + mountPath: /tmp/db-init.py + subPath: db-init.py + readOnly: true + volumes: + - name: grafana-bin + configMap: + name: grafana-bin + defaultMode: 0555 +{{- end }} diff --git a/grafana/templates/job-db-init.yaml b/grafana/templates/job-db-init.yaml new file mode 100644 index 000000000..06de4c034 --- /dev/null +++ b/grafana/templates/job-db-init.yaml @@ -0,0 +1,67 @@ +{{/* +Copyright 2017 The Openstack-Helm Authors. + +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. +*/}} + +{{- if .Values.manifests.job_db_init }} +{{- $envAll := . }} +{{- $dependencies := .Values.dependencies.db_init }} + +{{- $serviceAccountName := "grafana-db-init" }} +{{ tuple $envAll $dependencies $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: grafana-db-init +spec: + template: + metadata: + labels: +{{ tuple $envAll "grafana" "db-init" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }} + spec: + serviceAccountName: {{ $serviceAccountName }} + restartPolicy: OnFailure + nodeSelector: + {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }} + initContainers: +{{ tuple $envAll $dependencies list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }} + containers: + - name: grafana-db-init +{{ tuple $envAll "db_init" | include "helm-toolkit.snippets.image" | indent 10 }} +{{ tuple $envAll $envAll.Values.pod.resources.jobs.db_init | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }} + env: + - name: ROOT_DB_CONNECTION + valueFrom: + secretKeyRef: + name: {{ .Values.secrets.oslo_db.admin }} + key: DB_CONNECTION + - name: DB_CONNECTION + valueFrom: + secretKeyRef: + name: {{ .Values.secrets.oslo_db.user }} + key: DB_CONNECTION + command: + - /tmp/db-init.py + volumeMounts: + - name: grafana-bin + mountPath: /tmp/db-init.py + subPath: db-init.py + readOnly: true + volumes: + - name: grafana-bin + configMap: + name: grafana-bin + defaultMode: 0555 +{{- end }} diff --git a/grafana/templates/job-db-session-sync.yaml b/grafana/templates/job-db-session-sync.yaml new file mode 100644 index 000000000..439e7ea32 --- /dev/null +++ b/grafana/templates/job-db-session-sync.yaml @@ -0,0 +1,62 @@ +{{/* +Copyright 2017 The Openstack-Helm Authors. + +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. +*/}} + +{{- if .Values.manifests.job_db_session_sync }} +{{- $envAll := . }} +{{- $dependencies := .Values.dependencies.db_session_sync }} + +{{- $serviceAccountName := "grafana-db-session-sync" }} +{{ tuple $envAll $dependencies $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: grafana-db-session-sync +spec: + template: + metadata: + labels: +{{ tuple $envAll "grafana" "db-session-sync" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }} + spec: + serviceAccountName: {{ $serviceAccountName }} + restartPolicy: OnFailure + nodeSelector: + {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }} + initContainers: +{{ tuple $envAll $dependencies list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }} + containers: + - name: grafana-db-session-sync +{{ tuple $envAll "grafana_db_session_sync" | include "helm-toolkit.snippets.image" | indent 10 }} +{{ tuple $envAll $envAll.Values.pod.resources.jobs.db_session_sync | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }} + env: + - name: DB_CONNECTION + valueFrom: + secretKeyRef: + name: {{ .Values.secrets.oslo_db_session.user }} + key: DB_CONNECTION + command: + - /tmp/db-session-sync.py + volumeMounts: + - name: grafana-bin + mountPath: /tmp/db-session-sync.py + subPath: db-session-sync.py + readOnly: true + volumes: + - name: grafana-bin + configMap: + name: grafana-bin + defaultMode: 0555 +{{- end }} diff --git a/grafana/templates/job-prometheus-datasource.yaml b/grafana/templates/job-prometheus-datasource.yaml index 45221f555..45b69d99e 100644 --- a/grafana/templates/job-prometheus-datasource.yaml +++ b/grafana/templates/job-prometheus-datasource.yaml @@ -34,7 +34,7 @@ spec: serviceAccountName: {{ $serviceAccountName }} restartPolicy: OnFailure nodeSelector: - {{ .Values.labels.jobs.node_selector_key }}: {{ .Values.labels.jobs.node_selector_value }} + {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }} initContainers: {{ tuple $envAll .Values.pod_dependency list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }} containers: diff --git a/grafana/templates/secret-admin-creds.yaml b/grafana/templates/secret-admin-creds.yaml index 2cb168d47..53f410f7d 100644 --- a/grafana/templates/secret-admin-creds.yaml +++ b/grafana/templates/secret-admin-creds.yaml @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */}} -{{- if .Values.manifests.secret_admin }} +{{- if .Values.manifests.secret_admin_creds }} {{- $envAll := . }} --- apiVersion: v1 diff --git a/grafana/templates/secret-db-session.yaml b/grafana/templates/secret-db-session.yaml new file mode 100644 index 000000000..a2a62c240 --- /dev/null +++ b/grafana/templates/secret-db-session.yaml @@ -0,0 +1,30 @@ +{{/* +Copyright 2017 The Openstack-Helm Authors. + +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. +*/}} + +{{- if .Values.manifests.secret_db_session }} +{{- $envAll := . }} +{{- range $key1, $userClass := tuple "admin" "user" }} +{{- $secretName := index $envAll.Values.secrets.oslo_db_session $userClass }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} +type: Opaque +data: + DB_CONNECTION: {{ tuple "oslo_db_session" "internal" $userClass "mysql" $envAll | include "helm-toolkit.endpoints.authenticated_endpoint_uri_lookup" | b64enc -}} +{{- end }} +{{- end }} diff --git a/grafana/templates/secret-db.yaml b/grafana/templates/secret-db.yaml new file mode 100644 index 000000000..45d8802f1 --- /dev/null +++ b/grafana/templates/secret-db.yaml @@ -0,0 +1,30 @@ +{{/* +Copyright 2017 The Openstack-Helm Authors. + +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. +*/}} + +{{- if .Values.manifests.secret_db }} +{{- $envAll := . }} +{{- range $key1, $userClass := tuple "admin" "user" }} +{{- $secretName := index $envAll.Values.secrets.oslo_db $userClass }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} +type: Opaque +data: + DB_CONNECTION: {{ tuple "oslo_db" "internal" $userClass "mysql" $envAll | include "helm-toolkit.endpoints.authenticated_endpoint_uri_lookup" | b64enc -}} +{{- end }} +{{- end }} diff --git a/grafana/values.yaml b/grafana/values.yaml index 72c800324..336e6686e 100644 --- a/grafana/values.yaml +++ b/grafana/values.yaml @@ -21,6 +21,8 @@ images: grafana: docker.io/grafana/grafana:4.5.2 datasource: docker.io/kolla/ubuntu-source-heat-engine:3.0.3 dep_check: quay.io/stackanetes/kubernetes-entrypoint:v0.2.1 + db_init: docker.io/kolla/ubuntu-source-heat-engine:3.0.3 + grafana_db_session_sync: docker.io/kolla/ubuntu-source-heat-engine:3.0.3 image_repo_sync: docker.io/docker:17.07.0 pull_policy: IfNotPresent local_registry: @@ -30,17 +32,16 @@ images: - image_repo_sync labels: - jobs: - node_selector_key: openstack-control-plane - node_selector_value: enabled + node_selector_key: openstack-control-plane + node_selector_value: enabled pod: affinity: - anti: - type: - default: preferredDuringSchedulingIgnoredDuringExecution - topologyKey: - default: kubernetes.io/hostname + anti: + type: + default: preferredDuringSchedulingIgnoredDuringExecution + topologyKey: + default: kubernetes.io/hostname mounts: grafana: init_container: null @@ -75,6 +76,27 @@ pod: limits: memory: "1024Mi" cpu: "2000m" + db_init: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "1024Mi" + cpu: "2000m" + db_init_session: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "1024Mi" + cpu: "2000m" + grafana_db_session_sync: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "1024Mi" + cpu: "2000m" grafana: requests: memory: "128Mi" @@ -85,6 +107,42 @@ pod: endpoints: cluster_domain_suffix: cluster.local + oslo_db: + namespace: null + auth: + admin: + username: root + password: password + user: + username: grafana + password: password + hosts: + default: mariadb + host_fqdn_override: + default: null + path: /grafana + scheme: mysql+pymysql + port: + mysql: + default: 3306 + oslo_db_session: + namespace: null + auth: + admin: + username: root + password: password + user: + username: grafana_session + password: password + hosts: + default: mariadb + host_fqdn_override: + default: null + path: /grafana_session + scheme: mysql+pymysql + port: + mysql: + default: 3306 grafana: name: grafana namespace: null @@ -122,13 +180,31 @@ endpoints: public: 80 dependencies: - register_datasource: - jobs: + db_init: services: - - service: grafana - endpoint: internal + - service: oslo_db + endpoint: internal + db_init_session: + services: + - service: oslo_db + endpoint: internal + db_session_sync: + jobs: + - grafana-db-init-session + services: + - service: oslo_db + endpoint: internal + register_datasource: + services: + - service: grafana + endpoint: internal grafana: - services: null + jobs: + - grafana-db-init + - grafana-db-session-sync + services: + - service: oslo_db + endpoint: internal image_repo_sync: services: - service: local_image_registry @@ -150,8 +226,17 @@ network: port: 30902 ingress: public: true - proxy_body_size: 1024M + annotations: + kubernetes.io/ingress.class: "nginx" + ingress.kubernetes.io/rewrite-target: / +secrets: + oslo_db: + admin: grafana-db-admin + user: grafana-db-user + oslo_db_session: + admin: grafana-session-db-admin + user: grafana-session-db-user manifests: configmap_bin: true @@ -159,9 +244,14 @@ manifests: configmap_etc: true deployment: true ingress: true + job_db_init: true + job_db_init_session: true + job_db_session_sync: true job_datasource: true job_image_repo_sync: true - secret_admin: true + secret_db: true + secret_db_session: true + secret_admin_creds: true service: true service_ingress: true @@ -179,9 +269,11 @@ conf: server: protocol: http http_port: 3000 + database: + type: mysql session: - provider: file - provider_config: sessions + provider: mysql + provider_config: null cookie_name: grafana_sess cookie_secure: false session_life_time: 86400 diff --git a/tools/gate/chart-deploys/default.yaml b/tools/gate/chart-deploys/default.yaml index 750a19aab..ff049e6c2 100644 --- a/tools/gate/chart-deploys/default.yaml +++ b/tools/gate/chart-deploys/default.yaml @@ -155,6 +155,25 @@ charts: timeout: 300 output: false values: + dependencies: + grafana: + jobs: null + services: null + manifests: + ingress: false + job_db_init: false + job_db_init_session: false + job_db_session_sync: false + secret_db: false + secret_db_session: false + service_ingress: false + conf: + grafana: + database: + type: sqlite3 + session: + provider: file + provider_config: sessions network: grafana: ingress: