From 18dcbc384a55e30e357b3c94d5e48a65e7a0badb Mon Sep 17 00:00:00 2001 From: Tommy Carpenter Date: Tue, 4 Jun 2019 10:20:30 -0400 Subject: [PATCH] Add helm chart, may need rmr edits Change-Id: Id1822239494dfa40c35a62b2414652a2a927e5d8 Signed-off-by: Tommy Carpenter --- .gitignore | 1 + a1mediator/.helmignore | 22 ++++++++ a1mediator/Chart.yaml | 4 ++ a1mediator/files/ricmanifest.json | 63 +++++++++++++++++++++ a1mediator/files/rmr_string_int_mapping.txt | 4 ++ a1mediator/templates/_helpers.tpl | 45 +++++++++++++++ a1mediator/templates/config.yaml | 14 +++++ a1mediator/templates/deployment.yaml | 73 +++++++++++++++++++++++++ a1mediator/templates/helper.yaml | 3 + a1mediator/templates/ingress.yaml | 36 ++++++++++++ a1mediator/templates/secrets.yaml | 7 +++ a1mediator/templates/service.yaml | 36 ++++++++++++ a1mediator/templates/tests/test-connection.yaml | 15 +++++ a1mediator/values.yaml | 43 +++++++++++++++ docs/developer-guide.rst | 6 +- docs/index.rst | 12 ++++ integration_tests/docker-compose-only-tests.yml | 38 +++++++++++++ tox-integration.ini | 1 + 18 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 a1mediator/.helmignore create mode 100644 a1mediator/Chart.yaml create mode 100644 a1mediator/files/ricmanifest.json create mode 100644 a1mediator/files/rmr_string_int_mapping.txt create mode 100644 a1mediator/templates/_helpers.tpl create mode 100644 a1mediator/templates/config.yaml create mode 100644 a1mediator/templates/deployment.yaml create mode 100644 a1mediator/templates/helper.yaml create mode 100644 a1mediator/templates/ingress.yaml create mode 100644 a1mediator/templates/secrets.yaml create mode 100644 a1mediator/templates/service.yaml create mode 100644 a1mediator/templates/tests/test-connection.yaml create mode 100644 a1mediator/values.yaml create mode 100644 integration_tests/docker-compose-only-tests.yml diff --git a/.gitignore b/.gitignore index 4f07413..2cb6a1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +NOTES.txt .pytest_cache/ xunit-results.xml .DS_Store diff --git a/a1mediator/.helmignore b/a1mediator/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/a1mediator/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/a1mediator/Chart.yaml b/a1mediator/Chart.yaml new file mode 100644 index 0000000..3f8cbde --- /dev/null +++ b/a1mediator/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A1 Helm chart for Kubernetes +name: a1mediator +version: 0.8.2 diff --git a/a1mediator/files/ricmanifest.json b/a1mediator/files/ricmanifest.json new file mode 100644 index 0000000..211a115 --- /dev/null +++ b/a1mediator/files/ricmanifest.json @@ -0,0 +1,63 @@ +{ + "controls":[ + { + "name":"control_admission_time", + "description":"time period to allow dual connection", + "message_receives_rmr_type":"DC_ADMISSION_INTERVAL_CONTROL", + "message_receives_payload_schema":{ + "$schema":"http://json-schema.org/draft-07/schema#", + "type":"object", + "properties":{ + "dc_admission_start_time":{ + "type":"string", + "pattern":"^[0-9]{2}:[0-9]{2}:[0-9]{2}$" + }, + "dc_admission_end_time":{ + "type":"string", + "pattern":"^[0-9]{2}:[0-9]{2}:[0-9]{2}$" + } + }, + "required":[ + "dc_admission_start_time", + "dc_admission_end_time" + ] + }, + "message_sends_rmr_type":"DC_ADMISSION_INTERVAL_CONTROL_ACK", + "message_sends_payload_schema":{ + "$schema":"http://json-schema.org/draft-07/schema#", + "type":"object", + "properties":{ + "status":{ + "type":"string", + "enum":[ + "SUCCESS", + "FAIL" + ] + }, + "message":{ + "type":"string" + } + } + } + }, + { + "name":"test_policy", + "description":"for the purposes of testing", + "message_receives_rmr_type":"TEST_REQ", + "message_sends_rmr_type":"TEST_ACK", + "message_sends_payload_schema":{ + "$schema":"http://json-schema.org/draft-07/schema#", + "type":"object", + "properties":{ + "status":{ + "type":"string", + "enum":[ + "SUCCESS", + "FAIL" + ] + } + } + } + } + ] +} diff --git a/a1mediator/files/rmr_string_int_mapping.txt b/a1mediator/files/rmr_string_int_mapping.txt new file mode 100644 index 0000000..ff1479d --- /dev/null +++ b/a1mediator/files/rmr_string_int_mapping.txt @@ -0,0 +1,4 @@ +DC_ADMISSION_INTERVAL_CONTROL:20000 +DC_ADMISSION_INTERVAL_CONTROL_ACK:20001 +TEST_REQ:10000 +TEST_ACK:10001 diff --git a/a1mediator/templates/_helpers.tpl b/a1mediator/templates/_helpers.tpl new file mode 100644 index 0000000..fa46bab --- /dev/null +++ b/a1mediator/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "a1mediator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "a1mediator.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "a1mediator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "a1mediator.labels" -}} +app.kubernetes.io/name: {{ include "a1mediator.name" . }} +helm.sh/chart: {{ include "a1mediator.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} diff --git a/a1mediator/templates/config.yaml b/a1mediator/templates/config.yaml new file mode 100644 index 0000000..05f1630 --- /dev/null +++ b/a1mediator/templates/config.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: a1conf +data: + local.rt: | + newrt|start + rte|10000|rmr_delay_receiver:4563 + rte|20000|rmr_receiver:4560 + rte|10001|{{ .Values.rmrservice.name }}:{{ .Values.rmrservice.port }} + rte|20001|{{ .Values.rmrservice.name }}:{{ .Values.rmrservice.port }} + newrt|end + rmr_string_int_mapping.txt: {{ tpl (.Files.Get "files/rmr_string_int_mapping.txt") . | quote }} + ricmanifest.json: {{ tpl (.Files.Get "files/ricmanifest.json") . | quote }} diff --git a/a1mediator/templates/deployment.yaml b/a1mediator/templates/deployment.yaml new file mode 100644 index 0000000..a73ec1b --- /dev/null +++ b/a1mediator/templates/deployment.yaml @@ -0,0 +1,73 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "a1mediator.fullname" . }} + labels: +{{ include "a1mediator.labels" . | indent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "a1mediator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "a1mediator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + imagePullSecrets: + - name: "{{ .Values.lf_docker_reg_secret }}" + containers: + - name: {{ .Chart.Name }} + volumeMounts: + - name: a1conf + mountPath: /opt/ricmanifest.json + subPath: ricmanifest.json + - name: a1conf + mountPath: /opt/rmr_string_int_mapping.txt + subPath: rmr_string_int_mapping.txt + - name: a1conf + mountPath: /opt/route/local.rt + subPath: local.rt + env: + - name: PYTHONUNBUFFERED + value: "0" + - name: RMR_RCV_RETRY_INTERVAL + value: "{{ .Values.rmr_timeout_config.rcv_retry_interval_ms }}" + - name: RMR_RETRY_TIMES + value: "{{ .Values.rmr_timeout_config.rcv_retry_times }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.httpservice.port }} + protocol: TCP + + livenessProbe: + httpGet: + path: /ui + port: http + readinessProbe: + httpGet: + path: /ui + port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: "a1conf" + configMap: + name: "a1conf" + + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/a1mediator/templates/helper.yaml b/a1mediator/templates/helper.yaml new file mode 100644 index 0000000..c036840 --- /dev/null +++ b/a1mediator/templates/helper.yaml @@ -0,0 +1,3 @@ +{{- define "imagePullSecret" }} +{{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.imageCredentials.registry (printf "%s:%s" .Values.imageCredentials.username .Values.imageCredentials.password | b64enc) | b64enc }} +{{- end }} diff --git a/a1mediator/templates/ingress.yaml b/a1mediator/templates/ingress.yaml new file mode 100644 index 0000000..f1362d9 --- /dev/null +++ b/a1mediator/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "a1mediator.fullname" . -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: +{{ include "a1mediator.labels" . | indent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + backend: + serviceName: {{ $fullName }} + servicePort: http + {{- end }} + {{- end }} +{{- end }} diff --git a/a1mediator/templates/secrets.yaml b/a1mediator/templates/secrets.yaml new file mode 100644 index 0000000..4afe4ec --- /dev/null +++ b/a1mediator/templates/secrets.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: lfhelper +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ template "imagePullSecret" . }} diff --git a/a1mediator/templates/service.yaml b/a1mediator/templates/service.yaml new file mode 100644 index 0000000..fc67fc1 --- /dev/null +++ b/a1mediator/templates/service.yaml @@ -0,0 +1,36 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "a1mediator.fullname" . }} + labels: +{{ include "a1mediator.labels" . | indent 4 }} + +spec: + type: {{ .Values.httpservice.type }} + ports: + - port: {{ .Values.httpservice.port }} + targetPort: http + protocol: TCP + name: http + selector: + app.kubernetes.io/name: {{ include "a1mediator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + +--- + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.rmrservice.name }} + labels: +{{ include "a1mediator.labels" . | indent 4 }} + +spec: + type: {{ .Values.rmrservice.type }} + ports: + - port: {{ .Values.rmrservice.port }} + targetPort: {{ .Values.rmrservice.port }} + protocol: TCP + selector: + app.kubernetes.io/name: {{ include "a1mediator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/a1mediator/templates/tests/test-connection.yaml b/a1mediator/templates/tests/test-connection.yaml new file mode 100644 index 0000000..ca68368 --- /dev/null +++ b/a1mediator/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "a1mediator.fullname" . }}-test-connection" + labels: +{{ include "a1mediator.labels" . | indent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "a1mediator.fullname" . }}:{{ .Values.httpservice.port }}'] + restartPolicy: Never diff --git a/a1mediator/values.yaml b/a1mediator/values.yaml new file mode 100644 index 0000000..4375422 --- /dev/null +++ b/a1mediator/values.yaml @@ -0,0 +1,43 @@ +replicaCount: 1 + +image: + repository: nexus3.o-ran-sc.org:10004/ric-plt-a1 + tag: 0.8.2 + pullPolicy: IfNotPresent + +# name of the secret that allows for privagte registry docker pulls. +# if the value is "lfhelper", there is a helper function included in this chart, and it uses imageCredentials . +# imageCredentials is referenced in secrets.yaml, and uses a helper function to formulate the docker reg username and password into a valid dockerconfig.json. +# Note, if the value of lf_docker_reg_secret is changed, these image credentials are ignored and not used. +lf_docker_reg_secret: lfhelper +imageCredentials: + registry: nexus3.o-ran-sc.org:10004/ric-plt-a1 + username: + password: + +httpservice: + port: 10000 ## dont change this!! + type: ClusterIP + +rmrservice: + name: rmrservice + port: 4562 ## dont change this!! + type: ClusterIP + +rmr_timeout_config: + rcv_retry_interval_ms: 500 + rcv_retry_times: 20 + +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: [] + + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local diff --git a/docs/developer-guide.rst b/docs/developer-guide.rst index a2562ad..9dea8dd 100644 --- a/docs/developer-guide.rst +++ b/docs/developer-guide.rst @@ -37,7 +37,11 @@ This project follows semver. When changes are made, the versions are in: 3) ``container-tag.yaml`` -4) ``a1/openapi.yml`` +4) ``a1mediator/values.yaml`` + +5) ``a1mediator/Chart.yaml`` + +6) ``a1/openapi.yml`` Running locally =============== diff --git a/docs/index.rst b/docs/index.rst index 316ef9e..19bce13 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -64,6 +64,18 @@ which is an initial delay until the first rcv is tried. 2) timeouts and send failures should be retried before A1 gives up and returns a 503. The default is ``4``. +K8S +--- +The helm chart is in the folder `a1mediator`. + +There are two files in `a1mediator/files` that should be replaced with the "real" files for deployment. The ones included there, and referenced in the configmap, are only samples. To deploy A1 correctly, make sure these files are correct. + +:: + + helm install --devel a1mediator/ --name a1 --set imageCredentials.username=xxx --set imageCredentials.password=xxx + +The username and password here are the credentials to the registry defined in `a1mediator/values.yaml`. Currently this is the LF docker registry. + Docker ------ diff --git a/integration_tests/docker-compose-only-tests.yml b/integration_tests/docker-compose-only-tests.yml new file mode 100644 index 0000000..34facae --- /dev/null +++ b/integration_tests/docker-compose-only-tests.yml @@ -0,0 +1,38 @@ +# ================================================================================== +# Copyright (c) 2019 Nokia +# Copyright (c) 2018-2019 AT&T Intellectual Property. +# +# 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. +# ================================================================================== +version: '3' +services: + + rmr_receiver: + build: . + hostname: "rmr_receiver" + volumes: + - ./test_docker.rt:/opt/route/local.rt + + rmr_delay_receiver: + build: . + hostname: "rmr_delay_receiver" + volumes: + - ./test_docker.rt:/opt/route/local.rt + environment: + # https://github.com/docker/compose/issues/3878 + RMR_RCV_RETRY_INTERVAL: 500 + RMR_RETRY_TIMES: 10 + TEST_RCV_PORT: 4563 + TEST_RCV_RETURN_MINT: 10001 + TEST_RCV_SEC_DELAY: 5 + TEST_RCV_RETURN_PAYLOAD: '{"ACK_FROM": "DELAYED_TEST", "status": "SUCCESS"}' diff --git a/tox-integration.ini b/tox-integration.ini index e636aed..539da92 100644 --- a/tox-integration.ini +++ b/tox-integration.ini @@ -30,6 +30,7 @@ commands_pre= docker-compose up --build -d sleep 2 commands= +# helm lint a1mediator/ pytest -n 2 ab -n 100 -c 10 -u putdata -T application/json http://localhost:10000/ric/policies/control_admission_time commands_post= -- 2.16.6