This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch v1-10-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit 21f792ffb2c7ae041d766853d1aa5fe7191d4fe4
Author: Kamil BreguĊ‚a <[email protected]>
AuthorDate: Sat Oct 31 18:51:36 2020 +0100

    All k8s object must comply with JSON Schema (#12003)
    
    * All k8s resources should have global labels
    
    * All k8s object must comply with JSON Schema
    
    (cherry picked from commit 3c85c2c16e845fa7eafaadf7a7598428e4022c6f)
---
 .pre-commit-config.yaml                            |  4 +-
 chart/files/pod-template-file.kubernetes-helm-yaml |  9 +---
 chart/templates/redis/redis-statefulset.yaml       |  4 +-
 .../scheduler/scheduler-serviceaccount.yaml        |  6 +--
 chart/templates/secrets/redis-secrets.yaml         |  3 ++
 chart/templates/webserver/webserver-ingress.yaml   | 63 ++++++++++++++++++++++
 chart/templates/webserver/webserver-service.yaml   |  4 ++
 .../webserver/webserver-serviceaccount.yaml        | 10 ++--
 chart/templates/workers/worker-serviceaccount.yaml | 12 ++---
 chart/tests/helm_template_generator.py             | 37 +++++++++++++
 chart/tests/test_basic_helm_chart.py               | 22 +++++++-
 11 files changed, 146 insertions(+), 28 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 4dbf84c..2e27e50 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -272,14 +272,14 @@ repos:
                 ^\s*def\s*\S*\([^:#)]*:.*|          # Matches function param 
with Python3 type
                 ^\sdef\s*\S*\(.*\):\s*\-\>\s*\S*.*  # Matches -> return value 
syntax from Python3
             )$
-        exclude: ^dev|^scripts|^docs
+        exclude: ^dev|^scripts|^docs|^chart
         pass_filenames: true
       - id: python2-compile
         name: Compile code using python2
         language: system
         entry: python2.7 -m py_compile
         files: \.py$
-        exclude: ^dev|^scripts|^docs
+        exclude: ^dev|^scripts|^docs|^chart
         pass_filenames: true
         require_serial: true
       - id: incorrect-use-of-LoggingMixin
diff --git a/chart/files/pod-template-file.kubernetes-helm-yaml 
b/chart/files/pod-template-file.kubernetes-helm-yaml
index ed21d68..8647060 100644
--- a/chart/files/pod-template-file.kubernetes-helm-yaml
+++ b/chart/files/pod-template-file.kubernetes-helm-yaml
@@ -40,12 +40,7 @@ spec:
       volumeMounts:
         - mountPath: {{ template "airflow_logs" . }}
           name: airflow-logs
-{{- if or .Values.dags.persistence.enabled .Values.dags.gitSync.enabled }}
-        - mountPath: {{ template "airflow_dags_mount_path" . }}
-          name: airflow-dags
-          readOnly: false
-{{- end }}
-{{- if .Values.dags.gitSync.sshKeySecret }}
+{{- if .Values.dags.gitSync.knownHosts }}
         - mountPath: /etc/git-secret/known_hosts
           name: {{ .Values.dags.gitSync.knownHosts }}
           subPath: known_hosts
@@ -77,7 +72,7 @@ spec:
     {{ toYaml .Values.affinity | indent 8 }}
   tolerations:
     {{ toYaml .Values.tolerations | indent 8 }}
-  serviceAccountName: '{{ .Release.Name }}-worker-serviceaccount'
+  serviceAccountName: '{{ .Release.Name }}-worker'
   volumes:
   {{- if .Values.dags.persistence.enabled }}
   - name: dags
diff --git a/chart/templates/redis/redis-statefulset.yaml 
b/chart/templates/redis/redis-statefulset.yaml
index 6df78b4..ca47d97 100644
--- a/chart/templates/redis/redis-statefulset.yaml
+++ b/chart/templates/redis/redis-statefulset.yaml
@@ -48,10 +48,10 @@ spec:
 {{- with .Values.labels }}
 {{ toYaml . | indent 8 }}
 {{- end }}
+      {{- if .Values.redis.safeToEvict }}
       annotations:
-        {{- if .Values.redis.safeToEvict }}
         cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
-        {{- end }}
+      {{- end }}
     spec:
       nodeSelector:
 {{ toYaml .Values.nodeSelector | indent 8 }}
diff --git a/chart/templates/scheduler/scheduler-serviceaccount.yaml 
b/chart/templates/scheduler/scheduler-serviceaccount.yaml
index 5dfa1dc..f12991d 100644
--- a/chart/templates/scheduler/scheduler-serviceaccount.yaml
+++ b/chart/templates/scheduler/scheduler-serviceaccount.yaml
@@ -28,13 +28,13 @@ metadata:
     release: {{ .Release.Name }}
     chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
     heritage: {{ .Release.Service }}
+    {{- with .Values.labels }}
+    {{ toYaml . | nindent 4 }}
+    {{- end }}
   {{- with .Values.scheduler.serviceAccountAnnotations }}
   annotations:
     {{- range $key, $value := . }}
       {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
       {{- end }}
   {{- end }}
-{{- with .Values.labels }}
-{{ toYaml . | indent 4 }}
-{{- end }}
 {{- end }}
diff --git a/chart/templates/secrets/redis-secrets.yaml 
b/chart/templates/secrets/redis-secrets.yaml
index 7c9fe26..958474d 100644
--- a/chart/templates/secrets/redis-secrets.yaml
+++ b/chart/templates/secrets/redis-secrets.yaml
@@ -51,6 +51,9 @@ metadata:
     release: {{ .Release.Name }}
     chart: {{ .Chart.Name }}
     heritage: {{ .Release.Service }}
+    {{- with .Values.labels }}
+    {{ toYaml . | nindent 4 }}
+    {{- end }}
   annotations:
     "helm.sh/hook": "pre-install"
     "helm.sh/hook-delete-policy": "before-hook-creation"
diff --git a/chart/templates/webserver/webserver-ingress.yaml 
b/chart/templates/webserver/webserver-ingress.yaml
new file mode 100644
index 0000000..c249cb2
--- /dev/null
+++ b/chart/templates/webserver/webserver-ingress.yaml
@@ -0,0 +1,63 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+
+################################
+## Airflow Webserver Ingress
+#################################
+{{- if .Values.ingress.enabled }}
+apiVersion: networking.k8s.io/v1beta1
+kind: Ingress
+metadata:
+  name: {{ .Release.Name }}-airflow-ingress
+  labels:
+    tier: airflow
+    component: airflow-ingress
+    release: {{ .Release.Name }}
+    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
+    heritage: {{ .Release.Service }}
+  {{- with .Values.ingress.web.annotations }}
+  annotations:
+  {{ toYaml . | indent 4 }}
+  {{- end }}
+spec:
+  {{- if .Values.ingress.web.tls.enabled }}
+  tls:
+    - hosts:
+        - {{ .Values.ingress.web.host }}
+      secretName: {{ .Values.ingress.web.tls.secretName }}
+  {{- end }}
+  rules:
+    - http:
+        paths:
+          {{- range .Values.ingress.web.precedingPaths }}
+          - path: {{ .path }}
+            backend:
+              serviceName: {{ .serviceName }}
+              servicePort: {{ .servicePort }}
+          {{- end }}
+          - path: {{ .Values.ingress.web.path }}
+            backend:
+              serviceName: {{ .Release.Name }}-webserver
+              servicePort: airflow-ui
+          {{- range .Values.ingress.web.succeedingPaths }}
+          - path: {{ .path }}
+            backend:
+              serviceName: {{ .serviceName }}
+              servicePort: {{ .servicePort }}
+          {{- end }}
+      host: {{ .Values.ingress.web.host }}
+{{- end }}
diff --git a/chart/templates/webserver/webserver-service.yaml 
b/chart/templates/webserver/webserver-service.yaml
index 77f5995..feae23d 100644
--- a/chart/templates/webserver/webserver-service.yaml
+++ b/chart/templates/webserver/webserver-service.yaml
@@ -31,6 +31,10 @@ metadata:
 {{- with .Values.labels }}
 {{ toYaml . | indent 4 }}
 {{- end }}
+{{- with .Values.webserver.service.annotations }}
+  annotations:
+{{- toYaml . | nindent 4 }}
+{{- end }}
 spec:
   type: {{ .Values.webserver.service.type }}
   selector:
diff --git a/chart/templates/webserver/webserver-serviceaccount.yaml 
b/chart/templates/webserver/webserver-serviceaccount.yaml
index ba99cea..e42d767 100644
--- a/chart/templates/webserver/webserver-serviceaccount.yaml
+++ b/chart/templates/webserver/webserver-serviceaccount.yaml
@@ -27,12 +27,10 @@ metadata:
     release: {{ .Release.Name }}
     chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
     heritage: {{ .Release.Service }}
+    {{- with .Values.labels }}
+    {{ toYaml . | nindent 4 }}
+    {{- end }}
   {{- with .Values.webserver.serviceAccountAnnotations }}
   annotations:
-    {{- range $key, $value := . }}
-      {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
-      {{- end }}
+  {{ toYaml . | nindent 4 }}
   {{- end }}
-{{- with .Values.labels }}
-{{ toYaml . | indent 4 }}
-{{- end }}
diff --git a/chart/templates/workers/worker-serviceaccount.yaml 
b/chart/templates/workers/worker-serviceaccount.yaml
index 4a7542e..f87751b 100644
--- a/chart/templates/workers/worker-serviceaccount.yaml
+++ b/chart/templates/workers/worker-serviceaccount.yaml
@@ -28,13 +28,11 @@ metadata:
     release: {{ .Release.Name }}
     chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
     heritage: {{ .Release.Service }}
-  {{- with .Values.workers.serviceAccountAnnotations }}
+    {{- with .Values.labels }}
+    {{ toYaml . | nindent 4 }}
+    {{- end }}
+  {{- with .Values.workers.serviceAccountAnnotations}}
   annotations:
-    {{- range $key, $value := . }}
-      {{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
-      {{- end }}
+    {{ toYaml . | nindent 4 }}
   {{- end }}
-  {{- with .Values.labels }}
-{{ toYaml . | indent 4 }}
-{{- end }}
 {{- end }}
diff --git a/chart/tests/helm_template_generator.py 
b/chart/tests/helm_template_generator.py
index dccbb1e..ba870ed 100644
--- a/chart/tests/helm_template_generator.py
+++ b/chart/tests/helm_template_generator.py
@@ -17,13 +17,48 @@
 
 import subprocess
 import sys
+from functools import lru_cache
 from tempfile import NamedTemporaryFile
 
+import jmespath
+import jsonschema
+import requests
 import yaml
 from kubernetes.client.api_client import ApiClient
 
 api_client = ApiClient()
 
+BASE_URL_SPEC = 
"https://raw.githubusercontent.com/instrumenta/kubernetes-json-schema/master/v1.12.9";
+
+
+@lru_cache(maxsize=None)
+def create_validator(api_version, kind):
+    api_version = api_version.lower()
+    kind = kind.lower()
+
+    if '/' in api_version:
+        ext, _, api_version = api_version.partition("/")
+        ext = ext.split(".")[0]
+        url = f'{BASE_URL_SPEC}/{kind}-{ext}-{api_version}.json'
+    else:
+        url = f'{BASE_URL_SPEC}/{kind}-{api_version}.json'
+    request = requests.get(url)
+    request.raise_for_status()
+    schema = request.json()
+    jsonschema.Draft7Validator.check_schema(schema)
+    validator = jsonschema.Draft7Validator(schema)
+    return validator
+
+
+def validate_k8s_object(instance):
+    # Skip PostgresSQL chart
+    chart = jmespath.search("metadata.labels.chart", instance)
+    if chart and 'postgresql' in chart:
+        return
+
+    validate = create_validator(instance.get("apiVersion"), 
instance.get("kind"))
+    validate.validate(instance)
+
 
 def render_chart(name="RELEASE-NAME", values=None, show_only=None):
     """
@@ -41,6 +76,8 @@ def render_chart(name="RELEASE-NAME", values=None, 
show_only=None):
         templates = subprocess.check_output(command)
         k8s_objects = yaml.load_all(templates)
         k8s_objects = [k8s_object for k8s_object in k8s_objects if k8s_object] 
 # type: ignore
+        for k8s_object in k8s_objects:
+            validate_k8s_object(k8s_object)
         return k8s_objects
 
 
diff --git a/chart/tests/test_basic_helm_chart.py 
b/chart/tests/test_basic_helm_chart.py
index e535ac9..767a073 100644
--- a/chart/tests/test_basic_helm_chart.py
+++ b/chart/tests/test_basic_helm_chart.py
@@ -17,6 +17,8 @@
 
 import unittest
 
+import jmespath
+
 from tests.helm_template_generator import render_chart
 
 OBJECT_COUNT_IN_BASIC_DEPLOYMENT = 22
@@ -24,7 +26,15 @@ OBJECT_COUNT_IN_BASIC_DEPLOYMENT = 22
 
 class TestBaseChartTest(unittest.TestCase):
     def test_basic_deployments(self):
-        k8s_objects = render_chart("TEST-BASIC", {"chart": {'metadata': 'AA'}})
+        k8s_objects = render_chart(
+            "TEST-BASIC",
+            values={
+                "chart": {
+                    'metadata': 'AA',
+                },
+                'labels': {"TEST-LABEL": "TEST-VALUE"},
+            },
+        )
         list_of_kind_names_tuples = [
             (k8s_object['kind'], k8s_object['metadata']['name']) for 
k8s_object in k8s_objects
         ]
@@ -56,6 +66,16 @@ class TestBaseChartTest(unittest.TestCase):
             ],
         )
         self.assertEqual(OBJECT_COUNT_IN_BASIC_DEPLOYMENT, len(k8s_objects))
+        for k8s_object in k8s_objects:
+            labels = jmespath.search('metadata.labels', k8s_object) or {}
+            if 'postgresql' in labels.get('chart'):
+                continue
+            k8s_name = k8s_object['kind'] + ":" + 
k8s_object['metadata']['name']
+            self.assertEqual(
+                'TEST-VALUE',
+                labels.get("TEST-LABEL"),
+                f"Missing label TEST-LABEL on {k8s_name}. Current labels: 
{labels}",
+            )
 
     def test_basic_deployment_without_default_users(self):
         k8s_objects = render_chart("TEST-BASIC", {"webserver": {'defaultUser': 
{'enabled': False}}})

Reply via email to