From ec6b6cf412ded7fbcbdf19b816d21b7c6a2229ba Mon Sep 17 00:00:00 2001 From: "naman.gupta" Date: Mon, 12 Dec 2022 17:03:19 +0530 Subject: [PATCH] Files from python version needed from testing. Adding back files from python version needed from testing. Signed-off-by: naman.gupta Change-Id: I42b5c87c41a2efc25ac1cd63bc53e969882de48d --- .gitattributes | 25 + .gitignore | 115 ++++ .gitreview | 5 + integration_tests/a1mediator/.helmignore | 22 + integration_tests/a1mediator/Chart.yaml | 4 + .../a1mediator/templates/_helpers.tpl | 45 ++ integration_tests/a1mediator/templates/config.yaml | 12 + .../a1mediator/templates/deployment.yaml | 63 ++ integration_tests/a1mediator/templates/helper.yaml | 3 + .../a1mediator/templates/service.yaml | 56 ++ .../templates/tests/test-connection.yaml | 15 + integration_tests/a1mediator/values.yaml | 31 + integration_tests/dbaas-service/Chart.yaml | 25 + integration_tests/dbaas-service/README | 1 + .../dbaas-service/templates/deployment.yaml | 42 ++ .../dbaas-service/templates/service.yaml | 30 + integration_tests/dbaas-service/values.yaml | 30 + integration_tests/getlogs.sh | 20 + integration_tests/install_rmr.sh | 11 + integration_tests/portforward.sh | 8 + integration_tests/test_a1.tavern.yaml | 670 +++++++++++++++++++++ integration_tests/testreceiver/.helmignore | 22 + integration_tests/testreceiver/Chart.yaml | 5 + .../testreceiver/templates/_helpers.tpl | 45 ++ .../testreceiver/templates/config.yaml | 40 ++ .../testreceiver/templates/deployment.yaml | 93 +++ .../testreceiver/templates/service.yaml | 51 ++ integration_tests/testreceiver/values.yaml | 16 + .../testxappcode/Dockerfile-delay-receiver | 51 ++ .../testxappcode/Dockerfile-query-receiver | 51 ++ .../testxappcode/Dockerfile-test-receiver | 51 ++ .../testxappcode/delay-config-file.yaml | 38 ++ integration_tests/testxappcode/go.mod | 15 + .../testxappcode/query-config-file.yaml | 38 ++ integration_tests/testxappcode/receiver.go | 227 +++++++ .../testxappcode/test-config-file.yaml | 38 ++ local.rt | 4 + 37 files changed, 2018 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .gitreview create mode 100644 integration_tests/a1mediator/.helmignore create mode 100644 integration_tests/a1mediator/Chart.yaml create mode 100644 integration_tests/a1mediator/templates/_helpers.tpl create mode 100644 integration_tests/a1mediator/templates/config.yaml create mode 100644 integration_tests/a1mediator/templates/deployment.yaml create mode 100644 integration_tests/a1mediator/templates/helper.yaml create mode 100644 integration_tests/a1mediator/templates/service.yaml create mode 100644 integration_tests/a1mediator/templates/tests/test-connection.yaml create mode 100644 integration_tests/a1mediator/values.yaml create mode 100644 integration_tests/dbaas-service/Chart.yaml create mode 100644 integration_tests/dbaas-service/README create mode 100644 integration_tests/dbaas-service/templates/deployment.yaml create mode 100644 integration_tests/dbaas-service/templates/service.yaml create mode 100644 integration_tests/dbaas-service/values.yaml create mode 100644 integration_tests/getlogs.sh create mode 100644 integration_tests/install_rmr.sh create mode 100644 integration_tests/portforward.sh create mode 100644 integration_tests/test_a1.tavern.yaml create mode 100644 integration_tests/testreceiver/.helmignore create mode 100644 integration_tests/testreceiver/Chart.yaml create mode 100644 integration_tests/testreceiver/templates/_helpers.tpl create mode 100644 integration_tests/testreceiver/templates/config.yaml create mode 100644 integration_tests/testreceiver/templates/deployment.yaml create mode 100644 integration_tests/testreceiver/templates/service.yaml create mode 100644 integration_tests/testreceiver/values.yaml create mode 100644 integration_tests/testxappcode/Dockerfile-delay-receiver create mode 100644 integration_tests/testxappcode/Dockerfile-query-receiver create mode 100644 integration_tests/testxappcode/Dockerfile-test-receiver create mode 100644 integration_tests/testxappcode/delay-config-file.yaml create mode 100644 integration_tests/testxappcode/go.mod create mode 100644 integration_tests/testxappcode/query-config-file.yaml create mode 100644 integration_tests/testxappcode/receiver.go create mode 100644 integration_tests/testxappcode/test-config-file.yaml create mode 100644 local.rt diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d4628c1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,25 @@ +# https://help.github.com/articles/dealing-with-line-endings/ + +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized +# and converted to native line endings on checkout. +*.c text diff=cpp +*.cpp text diff=cpp +*.css text +*.go text diff=golang +*.htm text diff=html +*.html text diff=html +*.java text diff=java +*.js text +*.jsp text +*.less text +*.properties text +*.py text diff=python +*.sql text +*.xml text + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..45f74f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,115 @@ +# misc cruft +*.log +log.txt +integration_tests/log.txt +NOTES.txt +rmr/* +docs_and_diagrams/ + +# documentation +.tox +docs/_build/ + +# standard python ignore template +.pytest_cache/ +xunit-results.xml +.DS_Store +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +venv-tox/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +# Test report +xunit-reports +coverage-reports + +# Eclipse +.project +.pydevproject +.settings/ diff --git a/.gitreview b/.gitreview new file mode 100644 index 0000000..91493c1 --- /dev/null +++ b/.gitreview @@ -0,0 +1,5 @@ +[gerrit] +host=gerrit.o-ran-sc.org +port=29418 +project=ric-plt/a1/ +defaultbranch=master diff --git a/integration_tests/a1mediator/.helmignore b/integration_tests/a1mediator/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/integration_tests/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/integration_tests/a1mediator/Chart.yaml b/integration_tests/a1mediator/Chart.yaml new file mode 100644 index 0000000..1a4eb5b --- /dev/null +++ b/integration_tests/a1mediator/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A1 Helm chart for Kubernetes +name: a1mediator +version: 2.2.0 diff --git a/integration_tests/a1mediator/templates/_helpers.tpl b/integration_tests/a1mediator/templates/_helpers.tpl new file mode 100644 index 0000000..fa46bab --- /dev/null +++ b/integration_tests/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/integration_tests/a1mediator/templates/config.yaml b/integration_tests/a1mediator/templates/config.yaml new file mode 100644 index 0000000..811c118 --- /dev/null +++ b/integration_tests/a1mediator/templates/config.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: a1conf +data: + local.rt: | + newrt|start + mse|20010|6660666|testreceiverrmrservice:4560 + mse|20010|20001|delayreceiverrmrservice:4563 + # purposefully bad route to make sure rmr doesn't block on non listening receivers: + rte|20010|testreceiverrmrservice:4563 + newrt|end diff --git a/integration_tests/a1mediator/templates/deployment.yaml b/integration_tests/a1mediator/templates/deployment.yaml new file mode 100644 index 0000000..45b1a45 --- /dev/null +++ b/integration_tests/a1mediator/templates/deployment.yaml @@ -0,0 +1,63 @@ +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/route/local.rt + subPath: local.rt + env: + # this sets the source field in messages from a1 to point back to a1s service name, rather than it's random pod name + - name: RMR_SRC_ID + value: {{ .Values.rmrservice.name }} + - name: PYTHONUNBUFFERED + value: "1" + - name: A1_RMR_RETRY_TIMES + value: "{{ .Values.rmr_timeout_config.rcv_retry_times }}" + - name: INSTANCE_DELETE_NO_RESP_TTL + value: "5" + - name: INSTANCE_DELETE_RESP_TTL + value: "10" + - name: DBAAS_SERVICE_HOST + value: "dbaas" + - name: DBAAS_SERVICE_PORT + value: "6379" + + image: "a1:latest" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.httpservice.port }} + protocol: TCP + livenessProbe: + httpGet: + path: /a1-p/healthcheck + port: http + readinessProbe: + httpGet: + path: /a1-p/healthcheck + port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: "a1conf" + configMap: + name: "a1conf" diff --git a/integration_tests/a1mediator/templates/helper.yaml b/integration_tests/a1mediator/templates/helper.yaml new file mode 100644 index 0000000..c036840 --- /dev/null +++ b/integration_tests/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/integration_tests/a1mediator/templates/service.yaml b/integration_tests/a1mediator/templates/service.yaml new file mode 100644 index 0000000..3321aa6 --- /dev/null +++ b/integration_tests/a1mediator/templates/service.yaml @@ -0,0 +1,56 @@ +# This is the service for A1's external facing HTTP API +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 }} + +--- +# This is the service for rmr between A1 and the xapps +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 }} + +--- +# This is the service for the "hidden" port 4561 that rmr listens on for route manager +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.rmrrtemgrservice.name }} + labels: +{{ include "a1mediator.labels" . | indent 4 }} + +spec: + type: {{ .Values.rmrrtemgrservice.type }} + ports: + - port: {{ .Values.rmrrtemgrservice.port }} + targetPort: {{ .Values.rmrrtemgrservice.port }} + protocol: TCP + selector: + app.kubernetes.io/name: {{ include "a1mediator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/integration_tests/a1mediator/templates/tests/test-connection.yaml b/integration_tests/a1mediator/templates/tests/test-connection.yaml new file mode 100644 index 0000000..ca68368 --- /dev/null +++ b/integration_tests/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/integration_tests/a1mediator/values.yaml b/integration_tests/a1mediator/values.yaml new file mode 100644 index 0000000..e8bd0d2 --- /dev/null +++ b/integration_tests/a1mediator/values.yaml @@ -0,0 +1,31 @@ +replicaCount: 1 + +image: + repository: a1 + tag: latest + pullPolicy: Never + +# 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. +# This is the service for A1's external facing HTTP API +httpservice: + name: a1httpservice + port: 10000 # This is hardcoded in a1, probably dangerous to change + type: ClusterIP + +# This is the service for rmr between A1 and the xapps +rmrservice: + name: a1rmrservice + port: 4562 # This is hardcoded in a1, probably dangerous to change + type: ClusterIP + +# This is the service for the "hidden" port 4561 that rmr listens on for route manager +rmrrtemgrservice: + name: a1rmrrtemgrservice + port: 4561 # This is hardcoded in rmr, probably dangerous to change + type: ClusterIP + +# these are ENV variables that A1 takes; see docs +rmr_timeout_config: + rcv_retry_times: 20 diff --git a/integration_tests/dbaas-service/Chart.yaml b/integration_tests/dbaas-service/Chart.yaml new file mode 100644 index 0000000..8d183de --- /dev/null +++ b/integration_tests/dbaas-service/Chart.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# Copyright (c) 2019 Nokia. +# +# 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. + +# +# This source code is part of the near-RT RIC (RAN Intelligent Controller) +# platform project (RICP). +# + +apiVersion: v1 +appVersion: "1.0" +description: DBaaS realized with standalone, non-persistent, non-redundant Redis +name: dbaas +version: 0.1.0 diff --git a/integration_tests/dbaas-service/README b/integration_tests/dbaas-service/README new file mode 100644 index 0000000..c15a3e0 --- /dev/null +++ b/integration_tests/dbaas-service/README @@ -0,0 +1 @@ +This was stolen from https://gerrit.o-ran-sc.org/r/gitweb?p=ric-plt/dbaas.git diff --git a/integration_tests/dbaas-service/templates/deployment.yaml b/integration_tests/dbaas-service/templates/deployment.yaml new file mode 100644 index 0000000..8446b8e --- /dev/null +++ b/integration_tests/dbaas-service/templates/deployment.yaml @@ -0,0 +1,42 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# Copyright (c) 2019 Nokia. +# +# 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. + +# +# This source code is part of the near-RT RIC (RAN Intelligent Controller) +# platform project (RICP). +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.backend.name }} +spec: + replicas: {{ .Values.backend.replicas }} + selector: + matchLabels: + app: {{ .Values.backend.name }} + template: + metadata: + labels: + app: {{ .Values.backend.name }} + spec: + terminationGracePeriodSeconds: {{ .Values.backend.terminationGracePeriodSeconds }} + containers: + - image: {{ .Values.backend.image.name }}:{{ .Values.backend.image.tag }} + imagePullPolicy: {{ .Values.backend.image.imagePullPolicy }} + ports: + - containerPort: {{ .Values.backend.targetPort }} + name: {{ .Values.backend.name }} + restartPolicy: Always diff --git a/integration_tests/dbaas-service/templates/service.yaml b/integration_tests/dbaas-service/templates/service.yaml new file mode 100644 index 0000000..472aeac --- /dev/null +++ b/integration_tests/dbaas-service/templates/service.yaml @@ -0,0 +1,30 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# Copyright (c) 2019 Nokia. +# +# 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. + +# +# This source code is part of the near-RT RIC (RAN Intelligent Controller) +# platform project (RICP). +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Chart.Name }} +spec: + selector: + app: {{ .Values.backend.name }} + ports: + - port: {{ .Values.backend.port }} + targetPort: {{ .Values.backend.targetPort }} diff --git a/integration_tests/dbaas-service/values.yaml b/integration_tests/dbaas-service/values.yaml new file mode 100644 index 0000000..053ac96 --- /dev/null +++ b/integration_tests/dbaas-service/values.yaml @@ -0,0 +1,30 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# Copyright (c) 2019 Nokia. +# +# 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. + +# +# This source code is part of the near-RT RIC (RAN Intelligent Controller) +# platform project (RICP). +# + +backend: + terminationGracePeriodSeconds: 0 + replicas: 1 + name: "redis-standalone" + port: 6379 + targetPort: 6379 + image: + name: nexus3.o-ran-sc.org:10002/o-ran-sc/ric-plt-dbaas + tag: 0.2.2 + imagePullPolicy: IfNotPresent diff --git a/integration_tests/getlogs.sh b/integration_tests/getlogs.sh new file mode 100644 index 0000000..fbf2f1b --- /dev/null +++ b/integration_tests/getlogs.sh @@ -0,0 +1,20 @@ +#!/bin/sh +echo "\n\n a1" > log.txt +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^a1-a1mediator-' | xargs kubectl logs -p >> log.txt 2>&1 +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^a1-a1mediator-' | xargs kubectl logs >> log.txt 2>&1 + +echo "\n\n test receiver" >> log.txt +# the -p gets the "previous logs" in case the prior container crashed.. very useful for debugging a new receiver. +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^testreceiver-' | xargs -I X kubectl logs -p X testreceiver >> log.txt 2>&1 +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^testreceiver-' | xargs -I X kubectl logs X testreceiver >> log.txt 2>&1 + +echo "\n\n delay" >> log.txt +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^testreceiver-' | xargs -I X kubectl logs -p X delayreceiver >> log.txt 2>&1 +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^testreceiver-' | xargs -I X kubectl logs X delayreceiver >> log.txt 2>&1 + +echo "\n\n query" >> log.txt +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^testreceiver-' | xargs -I X kubectl logs -p X queryreceiver >> log.txt 2>&1 +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^testreceiver-' | xargs -I X kubectl logs X queryreceiver >> log.txt 2>&1 + +echo "\n\n sdl-redis" >> log.txt +kubectl get pods --namespace=default | awk '{ print $1 }' | egrep '^redis-standalone' | xargs kubectl logs >> log.txt 2>&1 diff --git a/integration_tests/install_rmr.sh b/integration_tests/install_rmr.sh new file mode 100644 index 0000000..2e58f37 --- /dev/null +++ b/integration_tests/install_rmr.sh @@ -0,0 +1,11 @@ +#!/bin/sh +git clone --branch 4.0.5 https://gerrit.oran-osc.org/r/ric-plt/lib/rmr \ + && cd rmr \ + && mkdir .build; cd .build \ + && echo "<<>>" \ + && cmake .. -DDEV_PKG=1; make install \ + && echo "<<< installing rmr .so>>>" \ + && cmake .. -DPACK_EXTERNALS=1; sudo make install \ + && echo "cleanup" \ + && cd ../.. \ + && rm -rf rmr diff --git a/integration_tests/portforward.sh b/integration_tests/portforward.sh new file mode 100644 index 0000000..17f56b7 --- /dev/null +++ b/integration_tests/portforward.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# fail on error +set -eux +pod=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=a1mediator,app.kubernetes.io/instance=a1" -o jsonpath="{.items[0].metadata.name}") +# this listener must run to forward the port, it's not just a config change +# it logs a line periodically that don't add much value, capture in a file. +rm forward.log +kubectl port-forward "$pod" 10000:10000 > forward.log 2>&1 & diff --git a/integration_tests/test_a1.tavern.yaml b/integration_tests/test_a1.tavern.yaml new file mode 100644 index 0000000..4657fcc --- /dev/null +++ b/integration_tests/test_a1.tavern.yaml @@ -0,0 +1,670 @@ +# test_a1.tavern.yaml + +test_name: test healthcheck + +stages: + - name: test the a1 healthcheck + request: + url: http://localhost:10000/a1-p/healthcheck + method: GET + response: + status_code: 200 + +--- + +test_name: test admission control + +stages: + - name: type not there yet + request: + url: http://localhost:10000/a1-p/policytypes/6660666 + method: GET + response: + status_code: 404 + + - name: type list empty + request: + url: http://localhost:10000/a1-p/policytypes + method: GET + response: + status_code: 200 + json: [] + + - name: instance list 404 + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies + method: GET + response: + status_code: 404 + + - name: put the type + request: + url: http://localhost:10000/a1-p/policytypes/6660666 + method: PUT + json: + name: Admission Control + description: various parameters to control admission of dual connection + policy_type_id: 6660666 + create_schema: + "$schema": http://json-schema.org/draft-07/schema# + type: object + additionalProperties: false + properties: + class: + type: integer + minimum: 1 + maximum: 256 + description: integer id representing class to which we are applying policy + enforce: + type: boolean + description: Whether to enable or disable enforcement of policy on this class + window_length: + type: integer + minimum: 15 + maximum: 300 + description: Sliding window length in seconds + trigger_threshold: + type: integer + minimum: 1 + blocking_rate: + type: number + minimum: 0 + maximum: 100 + required: + - class + - enforce + - window_length + - trigger_threshold + - blocking_rate + response: + status_code: 201 + + - name: type there now + request: + url: http://localhost:10000/a1-p/policytypes/6660666 + method: GET + response: + status_code: 200 + + - name: now in type list + request: + url: http://localhost:10000/a1-p/policytypes + method: GET + response: + status_code: 200 + json: [6660666] + + - name: instance list 200 but empty + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies + method: GET + response: + status_code: 200 + json: [] + + - name: test the admission control policy get not there yet + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy + method: GET + response: + status_code: 404 + + - name: test the admission control policy status get not there yet + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy/status + method: GET + response: + status_code: 404 + + - name: bad body for admission control policy + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy + method: PUT + json: + not: "expected" + headers: + content-type: application/json + response: + status_code: 400 + + - name: not a json + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy + method: PUT + data: "asdf" + response: + status_code: 415 + + # put it properly + - name: put the admission control policy instance + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy + method: PUT + json: + class: 12 + enforce: true + window_length: 20 + blocking_rate: 20 + trigger_threshold: 10 + headers: + content-type: application/json + response: + status_code: 202 + + - name: cant delete type with instances + delay_before: 3 # wait for the type acks to come back first + request: + url: http://localhost:10000/a1-p/policytypes/6660666 + method: DELETE + response: + status_code: 400 + + - name: test the admission control policy get + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy + method: GET + response: + status_code: 200 + json: + class: 12 + enforce: true + window_length: 20 + blocking_rate: 20 + trigger_threshold: 10 + + - name: test the admission control policy status get + delay_before: 10 # give it a few seconds for rmr + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy/status + method: GET + response: + status_code: 200 + json: + instance_status: "IN EFFECT" + has_been_deleted: False + created_at: !anyfloat + + - name: instance list 200 and contains the instance + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies + method: GET + response: + status_code: 200 + json: + - admission_control_policy + + # DELETE the instance and make sure subsequent GETs return properly + - name: delete the instance + delay_after: 4 + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy + method: DELETE + response: + status_code: 202 + + - name: status should now be not in effect but still there + delay_before: 3 # give it a few seconds for rmr + delay_after: 10 # 3 + 10 > 10; that is, wait until t2 expires + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy/status + method: GET + response: + status_code: 200 + json: + instance_status: "NOT IN EFFECT" + has_been_deleted: True + deleted_at: !anyfloat + created_at: !anyfloat + + - name: instance list 200 but no instance + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies + method: GET + response: + status_code: 200 + json: [] + + - name: cant get instance status + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy/status + method: GET + response: + status_code: 404 + + - name: cant get instance + request: + url: http://localhost:10000/a1-p/policytypes/6660666/policies/admission_control_policy + method: GET + response: + status_code: 404 + + - name: delete ac type + request: + url: http://localhost:10000/a1-p/policytypes/6660666 + method: DELETE + response: + status_code: 204 + + - name: cant delete again + request: + url: http://localhost:10000/a1-p/policytypes/6660666 + method: DELETE + response: + status_code: 404 + + - name: cant get + request: + url: http://localhost:10000/a1-p/policytypes/6660666 + method: DELETE + response: + status_code: 404 + + - name: empty type list + request: + url: http://localhost:10000/a1-p/policytypes + method: GET + response: + status_code: 200 + json: [] + + +--- + +test_name: test the delay receiver + +stages: + + - name: test the delay policy type not there yet + request: + url: http://localhost:10000/a1-p/policytypes/20001 + method: GET + response: + status_code: 404 + + - name: not yet in type list + request: + url: http://localhost:10000/a1-p/policytypes + method: GET + response: + status_code: 200 + json: [] + + - name: instance list 404 + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies + method: GET + response: + status_code: 404 + + - name: put the type + request: + url: http://localhost:10000/a1-p/policytypes/20001 + method: PUT + json: + name: test policy + description: just for testing + policy_type_id: 20001 + create_schema: + "$schema": http://json-schema.org/draft-07/schema# + type: object + properties: + test: + type: string + required: + - test + additionalProperties: false + response: + status_code: 201 + + - name: type there now + request: + url: http://localhost:10000/a1-p/policytypes/20001 + method: GET + response: + status_code: 200 + json: + name: test policy + description: just for testing + policy_type_id: 20001 + create_schema: + "$schema": http://json-schema.org/draft-07/schema# + type: object + properties: + test: + type: string + required: + - test + additionalProperties: false + + - name: now in type list + request: + url: http://localhost:10000/a1-p/policytypes + method: GET + response: + status_code: 200 + json: + - 20001 + + - name: instance list 200 but empty + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies + method: GET + response: + status_code: 200 + json: [] + + - name: test the delay policy instance get not there yet + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest + method: GET + response: + status_code: 404 + + - name: test the delay policy status get not there yet + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest/status + method: GET + response: + status_code: 404 + + - name: bad body for delaytest + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest + method: PUT + json: + not: "welcome" + response: + status_code: 400 + + - name: create delay policy instance + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest + method: PUT + json: + test: foo + headers: + content-type: application/json + response: + status_code: 202 + + - name: test the delay status get, not in effect yet + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest/status + method: GET + response: + status_code: 200 + json: + instance_status: "NOT IN EFFECT" + has_been_deleted: False + created_at: !anyfloat + + - name: test the delay policy get + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest + method: GET + response: + status_code: 200 + json: + test: foo + + - name: instance list 200 and there + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies + method: GET + response: + status_code: 200 + json: + - delaytest + + - name: test the delay status get + max_retries: 3 + delay_before: 6 # give it a few seconds for rmr ; delay reciever sleeps for 5 seconds by default + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest/status + method: GET + response: + status_code: 200 + json: + instance_status: "IN EFFECT" + has_been_deleted: False + created_at: !anyfloat + + # DELETE the instance and make sure subsequent GETs return properly + - name: delete the instance + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest + method: DELETE + response: + status_code: 202 + + - name: test the delay status get immediately + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest/status + method: GET + response: + status_code: 200 + json: + instance_status: "IN EFFECT" + has_been_deleted: True + deleted_at: !anyfloat + created_at: !anyfloat + + - name: test the delay status get after delay but before timers + delay_before: 7 + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest/status + method: GET + response: + status_code: 200 + json: + instance_status: "NOT IN EFFECT" + has_been_deleted: True + deleted_at: !anyfloat + created_at: !anyfloat + + - name: test the delay status get after delay and after the timers + delay_before: 7 + request: + url: http://localhost:10000/a1-p/policytypes/20001/policies/delaytest/status + method: GET + response: + status_code: 404 + +--- + +test_name: test query + +stages: + - name: type not there yet + request: + url: http://localhost:10000/a1-p/policytypes/1006001 + method: GET + response: + status_code: 404 + + - name: put the type + request: + url: http://localhost:10000/a1-p/policytypes/1006001 + method: PUT + json: + name: query test + description: test + policy_type_id: 1006001 + create_schema: + "$schema": http://json-schema.org/draft-07/schema# + type: object + additionalProperties: false + properties: + foo: + type: string + required: + - foo + response: + status_code: 201 + + - name: type there now + request: + url: http://localhost:10000/a1-p/policytypes/1006001 + method: GET + response: + status_code: 200 + + - name: instance list 200 but empty + request: + url: http://localhost:10000/a1-p/policytypes/1006001/policies + method: GET + response: + status_code: 200 + json: [] + + - name: instance 1 + request: + url: http://localhost:10000/a1-p/policytypes/1006001/policies/qt1 + method: PUT + json: + foo: "bar1" + headers: + content-type: application/json + response: + status_code: 202 + + - name: instance 2 + request: + url: http://localhost:10000/a1-p/policytypes/1006001/policies/qt2 + method: PUT + json: + foo: "bar2" + headers: + content-type: application/json + response: + status_code: 202 + + - name: instance list + request: + url: http://localhost:10000/a1-p/policytypes/1006001/policies + method: GET + response: + status_code: 200 + json: [qt1, qt2] + + # after the query, a1 should send, query receiver should send back, and the policy should be in effect + # sometimes in kubernetes, this test takes a long time to work because of an k8s issue + # empirically we find that the si95 rmr finally "detects" failure after about 75 seconds, retries, and then works. + - name: test the query status get + max_retries: 100 + delay_before: 1 + request: + url: http://localhost:10000/a1-p/policytypes/1006001/policies/qt1/status + method: GET + response: + status_code: 200 + json: + instance_status: "IN EFFECT" + has_been_deleted: False + created_at: !anyfloat + + - name: test the query status get 2 + max_retries: 100 + delay_before: 1 + request: + url: http://localhost:10000/a1-p/policytypes/1006001/policies/qt2/status + method: GET + response: + status_code: 200 + json: + instance_status: "IN EFFECT" + has_been_deleted: False + created_at: !anyfloat + +--- + +test_name: test bad routing file endpoint + +stages: + + - name: put the type + request: + url: http://localhost:10000/a1-p/policytypes/20002 + method: PUT + json: + name: test policy + description: just for testing + policy_type_id: 20002 + create_schema: + "$schema": http://json-schema.org/draft-07/schema# + type: object + properties: + test: + type: string + required: + - test + additionalProperties: false + + - name: create policy instance that will go to a broken routing endpoint + request: + url: http://localhost:10000/a1-p/policytypes/20002/policies/brokentest + method: PUT + json: + test: foo + headers: + content-type: application/json + response: + status_code: 202 + + - name: should be no status + request: + url: http://localhost:10000/a1-p/policytypes/20002/policies/brokentest/status + method: GET + response: + status_code: 200 + json: [] + + # this one cant currently be deleted, see the comment in a1/data.py + +--- + +test_name: bad_requests + +stages: + + - name: bad type get + request: + url: http://localhost:10000/a1-p/policytypes/20666 + method: GET + response: + status_code: 404 + + - name: bad instance get bad type + request: + url: http://localhost:10000/a1-p/policytypes/20666/policies/nonono + method: GET + response: + status_code: 404 + + - name: bad int range 1 + request: + url: http://localhost:10000/a1-p/policytypes/0 + method: PUT + json: + name: test policy + description: just for testing + policy_type_id: 0 + create_schema: + "$schema": http://json-schema.org/draft-07/schema# + type: object + response: + status_code: 400 + + - name: bad int range 2 + request: + url: http://localhost:10000/a1-p/policytypes/2147483648 + method: PUT + json: + name: test policy + description: just for testing + policy_type_id: 2147483648 + create_schema: + "$schema": http://json-schema.org/draft-07/schema# + type: object + response: + status_code: 400 diff --git a/integration_tests/testreceiver/.helmignore b/integration_tests/testreceiver/.helmignore new file mode 100644 index 0000000..50af031 --- /dev/null +++ b/integration_tests/testreceiver/.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/integration_tests/testreceiver/Chart.yaml b/integration_tests/testreceiver/Chart.yaml new file mode 100644 index 0000000..917669d --- /dev/null +++ b/integration_tests/testreceiver/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: Test receiver for a1 integration tests +name: testreceiver +version: 0.1.0 diff --git a/integration_tests/testreceiver/templates/_helpers.tpl b/integration_tests/testreceiver/templates/_helpers.tpl new file mode 100644 index 0000000..f35130c --- /dev/null +++ b/integration_tests/testreceiver/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "testreceiver.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 "testreceiver.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 "testreceiver.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "testreceiver.labels" -}} +app.kubernetes.io/name: {{ include "testreceiver.name" . }} +helm.sh/chart: {{ include "testreceiver.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/integration_tests/testreceiver/templates/config.yaml b/integration_tests/testreceiver/templates/config.yaml new file mode 100644 index 0000000..dd4772b --- /dev/null +++ b/integration_tests/testreceiver/templates/config.yaml @@ -0,0 +1,40 @@ +#note: the xapp frame calls rmrready, which requires a route table, even if the app only uses rts. So we can never fully delete these. +# +apiVersion: v1 +kind: ConfigMap +metadata: + name: testreceiverconf +data: + local.rt: | + newrt|start + # right now the test receivers in go cannot use rts so we need this. See the comment in the receiver xapp + rte|20011|a1rmrservice:4562 + newrt|end + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: delayreceiverconf +data: + local.rt: | + newrt|start + # right now the test receivers in go cannot use rts so we need this. See the comment in the receiver xapp + rte|20011|a1rmrservice:4562 + newrt|end + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: queryreceiverconf +data: + local.rt: | + newrt|start + # this query is initiated in the query receiver + rte|20012|a1rmrservice:4562 + # right now the test receivers in go cannot use rts so we need this. See the comment in the receiver xapp + rte|20011|a1rmrservice:4562 + newrt|end diff --git a/integration_tests/testreceiver/templates/deployment.yaml b/integration_tests/testreceiver/templates/deployment.yaml new file mode 100644 index 0000000..af17968 --- /dev/null +++ b/integration_tests/testreceiver/templates/deployment.yaml @@ -0,0 +1,93 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "testreceiver.fullname" . }} + labels: +{{ include "testreceiver.labels" . | indent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "testreceiver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "testreceiver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + #query receiver + - name: queryreceiver + image: queryreceiver:latest + imagePullPolicy: Never + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: queryreceiverconf + mountPath: /opt/route/local.rt + subPath: local.rt + env: + # tells the test xapp to do a query + - name: DO_QUERY + value: "YES" + # this sets the source field in messages from a1 to point back to a1s service name, rather than it's random pod name + - name: RMR_SRC_ID + value: {{ .Values.queryrmrservice.name }} + - name: HANDLER_ID + value: "query_tester" + # the xapp framework requires this to work, even if SDL isn't used. + # it does an SDL healthcheck before it starts up properly + # moreover, the db config section doesn't appear to be honored; with that set, but not this, it doesn't find SDL + # so we need this here for the test receiver which uses the xapp framework to work + - name: DBAAS_SERVICE_HOST + value: "dbaas" + - name: DBAAS_SERVICE_PORT + value: "6379" + + # test receiver + - name: testreceiver + image: testreceiver:latest + imagePullPolicy: Never + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: testreceiverconf + mountPath: /opt/route/local.rt + subPath: local.rt + env: + - name: DBAAS_SERVICE_HOST + value: "dbaas" + - name: DBAAS_SERVICE_PORT + value: "6379" + + # test receiver that delays until sending + - name: delayreceiver + image: delayreceiver:latest + imagePullPolicy: Never + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: delayreceiverconf + mountPath: /opt/route/local.rt + subPath: local.rt + env: + - name: TEST_RCV_SEC_DELAY + value: "5" + - name: HANDLER_ID + value: "delay_receiver" + - name: DBAAS_SERVICE_HOST + value: "dbaas" + - name: DBAAS_SERVICE_PORT + value: "6379" + + volumes: + - name: "testreceiverconf" + configMap: + name: "testreceiverconf" + - name: "delayreceiverconf" + configMap: + name: "delayreceiverconf" + - name: "queryreceiverconf" + configMap: + name: "queryreceiverconf" diff --git a/integration_tests/testreceiver/templates/service.yaml b/integration_tests/testreceiver/templates/service.yaml new file mode 100644 index 0000000..ecb90a0 --- /dev/null +++ b/integration_tests/testreceiver/templates/service.yaml @@ -0,0 +1,51 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.testrmrservice.name }} + labels: +{{ include "testreceiver.labels" . | indent 4 }} +spec: + type: {{ .Values.testrmrservice.type }} + ports: + - port: {{ .Values.testrmrservice.port }} + targetPort: {{ .Values.testrmrservice.port }} + protocol: TCP + selector: + app.kubernetes.io/name: {{ include "testreceiver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + +--- + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.delayrmrservice.name }} + labels: +{{ include "testreceiver.labels" . | indent 4 }} +spec: + type: {{ .Values.delayrmrservice.type }} + ports: + - port: {{ .Values.delayrmrservice.port }} + targetPort: {{ .Values.delayrmrservice.port }} + protocol: TCP + selector: + app.kubernetes.io/name: {{ include "testreceiver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + +--- + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.queryrmrservice.name }} + labels: +{{ include "testreceiver.labels" . | indent 4 }} +spec: + type: {{ .Values.queryrmrservice.type }} + ports: + - port: {{ .Values.queryrmrservice.port }} + targetPort: {{ .Values.queryrmrservice.port }} + protocol: TCP + selector: + app.kubernetes.io/name: {{ include "testreceiver.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/integration_tests/testreceiver/values.yaml b/integration_tests/testreceiver/values.yaml new file mode 100644 index 0000000..f045b63 --- /dev/null +++ b/integration_tests/testreceiver/values.yaml @@ -0,0 +1,16 @@ +replicaCount: 1 + +testrmrservice: + name: testreceiverrmrservice + type: ClusterIP + port: 4560 + +delayrmrservice: + name: delayreceiverrmrservice + type: ClusterIP + port: 4563 + +queryrmrservice: + name: queryreceiverrmrservice + type: ClusterIP + port: 4564 diff --git a/integration_tests/testxappcode/Dockerfile-delay-receiver b/integration_tests/testxappcode/Dockerfile-delay-receiver new file mode 100644 index 0000000..5c1c239 --- /dev/null +++ b/integration_tests/testxappcode/Dockerfile-delay-receiver @@ -0,0 +1,51 @@ +# ================================================================================== +# Copyright (c) 2020 Nokia +# Copyright (c) 2020 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. +# ================================================================================== + +# This Dockerfile uses a two stage Docker build +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/bldr-alpine3:12-a3.11 + +# copy rmr headers and libraries from builder image in lieu of an Alpine package +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/include/rmr /usr/local/include/rmr +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/lib64/librmr* /usr/local/lib64/ + +# go will complain if there is a go.mod at the root of the GOPATH so we can't. +RUN mkdir myxapp +COPY receiver.go myxapp/receiver.go +COPY go.mod myxapp/go.mod + +# do the build +WORKDIR myxapp +ENV GO111MODULE on +ENV GO_ENABLED 0 +ENV GOOS linux +RUN go build -a -installsuffix cgo -o receiver receiver.go + +# 2nd stage +FROM alpine:3.11 + +# copy rmr libraries from builder image in lieu of an Alpine package +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/lib64/librmr* /usr/local/lib64/ + +COPY --from=0 /myxapp/receiver . +COPY delay-config-file.yaml . + +# rmr setup +RUN mkdir -p /opt/route/ +ENV LD_LIBRARY_PATH /usr/local/lib:/usr/local/lib64 +ENV RMR_SEED_RT /opt/route/local.rt + +CMD ["./receiver", "-f", "delay-config-file.yaml"] diff --git a/integration_tests/testxappcode/Dockerfile-query-receiver b/integration_tests/testxappcode/Dockerfile-query-receiver new file mode 100644 index 0000000..a7dd178 --- /dev/null +++ b/integration_tests/testxappcode/Dockerfile-query-receiver @@ -0,0 +1,51 @@ +# ================================================================================== +# Copyright (c) 2020 Nokia +# Copyright (c) 2020 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. +# ================================================================================== + +# This Dockerfile uses a two stage Docker build +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/bldr-alpine3:12-a3.11 + +# copy rmr headers and libraries from builder image in lieu of an Alpine package +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/include/rmr /usr/local/include/rmr +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/lib64/librmr* /usr/local/lib64/ + +# go will complain if there is a go.mod at the root of the GOPATH so we can't. +RUN mkdir myxapp +COPY receiver.go myxapp/receiver.go +COPY go.mod myxapp/go.mod + +# do the build +WORKDIR myxapp +ENV GO111MODULE on +ENV GO_ENABLED 0 +ENV GOOS linux +RUN go build -a -installsuffix cgo -o receiver receiver.go + +# 2nd stage +FROM alpine:3.11 + +# copy rmr libraries from builder image in lieu of an Alpine package +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/lib64/librmr* /usr/local/lib64/ + +COPY --from=0 /myxapp/receiver . +COPY query-config-file.yaml . + +# rmr setup +RUN mkdir -p /opt/route/ +ENV LD_LIBRARY_PATH /usr/local/lib:/usr/local/lib64 +ENV RMR_SEED_RT /opt/route/local.rt + +CMD ["./receiver", "-f", "query-config-file.yaml"] diff --git a/integration_tests/testxappcode/Dockerfile-test-receiver b/integration_tests/testxappcode/Dockerfile-test-receiver new file mode 100644 index 0000000..196f256 --- /dev/null +++ b/integration_tests/testxappcode/Dockerfile-test-receiver @@ -0,0 +1,51 @@ +# ================================================================================== +# Copyright (c) 2020 Nokia +# Copyright (c) 2020 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. +# ================================================================================== + +# This Dockerfile uses a two stage Docker build +FROM nexus3.o-ran-sc.org:10004/o-ran-sc/bldr-alpine3:12-a3.11 + +# copy rmr headers and libraries from builder image in lieu of an Alpine package +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/include/rmr /usr/local/include/rmr +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/lib64/librmr* /usr/local/lib64/ + +# go will complain if there is a go.mod at the root of the GOPATH so we can't. +RUN mkdir myxapp +COPY receiver.go myxapp/receiver.go +COPY go.mod myxapp/go.mod + +# do the build +WORKDIR myxapp +ENV GO111MODULE on +ENV GO_ENABLED 0 +ENV GOOS linux +RUN go build -a -installsuffix cgo -o receiver receiver.go + +# 2nd stage +FROM alpine:3.11 + +# copy rmr libraries from builder image in lieu of an Alpine package +COPY --from=nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-alpine3-rmr:4.0.5 /usr/local/lib64/librmr* /usr/local/lib64/ + +COPY --from=0 /myxapp/receiver . +COPY test-config-file.yaml . + +# rmr setup +RUN mkdir -p /opt/route/ +ENV LD_LIBRARY_PATH /usr/local/lib:/usr/local/lib64 +ENV RMR_SEED_RT /opt/route/local.rt + +CMD ["./receiver", "-f", "test-config-file.yaml"] diff --git a/integration_tests/testxappcode/delay-config-file.yaml b/integration_tests/testxappcode/delay-config-file.yaml new file mode 100644 index 0000000..8db59f7 --- /dev/null +++ b/integration_tests/testxappcode/delay-config-file.yaml @@ -0,0 +1,38 @@ +# Copyright (c) 2019-2020 AT&T Intellectual Property. +# Copyright (c) 2019-2020 Nokia. +# +# 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. + +"local": + "host": ":8080" +"logger": + "level": 4 +"rmr": + "protPort": "tcp:4563" + "maxSize": 4096 + "numWorkers": 1 +"db": + "host": "dbaas" + "port": 6379 + "namespaces": ["sdl", "rnib"] +"test": + "mode": "forwarder" + "mtype": 10004 + "subId": 1111 + "size": 100 + "rate": 10 + "amount": 10 + "rounds": 1 + "store": 0 + "waitForAck": 0 + diff --git a/integration_tests/testxappcode/go.mod b/integration_tests/testxappcode/go.mod new file mode 100644 index 0000000..7e202d4 --- /dev/null +++ b/integration_tests/testxappcode/go.mod @@ -0,0 +1,15 @@ +go 1.13 + +module gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/example-xapp + +require ( + gerrit.o-ran-sc.org/r/ric-plt/xapp-frame v0.4.8 + github.com/go-openapi/runtime v0.19.11 // indirect + github.com/go-openapi/spec v0.19.6 // indirect +) + +replace gerrit.o-ran-sc.org/r/ric-plt/xapp-frame => gerrit.o-ran-sc.org/r/ric-plt/xapp-frame.git v0.4.8 + +replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.7.0 + +replace gerrit.o-ran-sc.org/r/com/golog => gerrit.o-ran-sc.org/r/com/golog.git v0.0.1 diff --git a/integration_tests/testxappcode/query-config-file.yaml b/integration_tests/testxappcode/query-config-file.yaml new file mode 100644 index 0000000..871d166 --- /dev/null +++ b/integration_tests/testxappcode/query-config-file.yaml @@ -0,0 +1,38 @@ +# Copyright (c) 2019-2020 AT&T Intellectual Property. +# Copyright (c) 2019-2020 Nokia. +# +# 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. + +"local": + "host": ":8080" +"logger": + "level": 4 +"rmr": + "protPort": "tcp:4564" + "maxSize": 4096 + "numWorkers": 1 +"db": + "host": "dbaas" + "port": 6379 + "namespaces": ["sdl", "rnib"] +"test": + "mode": "forwarder" + "mtype": 10004 + "subId": 1111 + "size": 100 + "rate": 10 + "amount": 10 + "rounds": 1 + "store": 0 + "waitForAck": 0 + diff --git a/integration_tests/testxappcode/receiver.go b/integration_tests/testxappcode/receiver.go new file mode 100644 index 0000000..9012094 --- /dev/null +++ b/integration_tests/testxappcode/receiver.go @@ -0,0 +1,227 @@ +/* +================================================================================== + Copyright (c) 2020 AT&T Intellectual Property. + Copyright (c) 2020 Nokia + + 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. +================================================================================== +*/ +package main + +import ( + "encoding/json" + "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" + "os" + "strconv" + "time" +) + +var delay int // used for the delay receiver +var handlerID string // used for the delay receiver too +var doQuery bool // used for the query receiver + +type a1Receiver struct { + msgChan chan *xapp.RMRParams + appReady bool + rmrReady bool +} + +type policyRequest struct { + Operation string `json:"operation"` + PolicyTypeID int `json:"policy_type_id"` + PolicyInstanceID string `json:"policy_instance_id"` + Pay interface{} `json:"payload"` +} + +type policyRequestResponse struct { + PolicyTypeID int `json:"policy_type_id"` + PolicyInstanceID string `json:"policy_instance_id"` + HandlerID string `json:"handler_id"` + Status string `json:"status"` +} + +type policyQuery struct { + PolicyTypeID int `json:"policy_type_id"` +} + +func (e *a1Receiver) sendMsgRetry(params *xapp.RMRParams) { + // helper for rmr that handles retries and sleep + retries := 0 + for { // just keep trying until it works + if e.rmrReady { // we must wait for ready, else SendMsg will blow with a nullptr + if ok := xapp.Rmr.SendMsg(params); ok { + xapp.Logger.Info("Msg successfully sent after %d retries!", retries) + return + } + retries++ + //xapp.Logger.Info("Query failed to send...") + } else { + xapp.Logger.Info("rmr not ready...") + time.Sleep(time.Duration(1) * time.Second) + } + } +} + +func (e *a1Receiver) handlePolicyReq(msg *xapp.RMRParams) { + + // unmarshal the request + var dat policyRequest + if err := json.Unmarshal(msg.Payload, &dat); err != nil { + panic(err) + } + + var status string + switch dat.Operation { + case "CREATE": + status = "OK" + case "DELETE": + status = "DELETED" + } + + // form the response + res := &policyRequestResponse{ + dat.PolicyTypeID, + dat.PolicyInstanceID, + "test_receiver", + status, + } + + outgoing, err := json.Marshal(res) + if err != nil { + panic(err) + } + + /* + WARNING: + we want to use rts here. However, the current go xapp framework rts is broken. + */ + params := &xapp.RMRParams{ + Mtype: 20011, + Payload: outgoing, + } + + if delay > 0 { + xapp.Logger.Info("Xapp is sleeping...") + time.Sleep(time.Duration(delay) * time.Second) // so much work to replicate python's time.sleep(5)... + } + + e.sendMsgRetry(params) + + xapp.Logger.Info("Policy response sent!") +} + +func (e *a1Receiver) sendQuery() { + // form the query + res := &policyQuery{ + 1006001, + } + outgoing, err := json.Marshal(res) + if err != nil { + panic(err) + } + params := &xapp.RMRParams{ + Mtype: 20012, + Payload: outgoing, + } + + for { + /* We do this in a loop here, because even when the query first works, it could be the case that + a1 does not even have the type yet, or there are no instances yet. In this integration test, + we just keep pounding away so that eventually a1 returns the list this int test is looking for. + A real xapp would NOT call the query in a loop like this. + */ + e.sendMsgRetry(params) + xapp.Logger.Info("Query sent successfully") + time.Sleep(time.Duration(1) * time.Second) + } +} + +func (e *a1Receiver) messageLoop() { + for { + xapp.Logger.Info("Waiting for message..") + + msg := <-e.msgChan + + xapp.Logger.Info("Message received!") + defer xapp.Rmr.Free(msg.Mbuf) + + switch msg.Mtype { + case 20010: + e.handlePolicyReq(msg) + default: + panic("Unexpected message type!") + } + } +} + +// Consume: This named function is a required callback for e to use the xapp interface. it is called on all received rmr messages. +func (e *a1Receiver) Consume(rp *xapp.RMRParams) (err error) { + e.msgChan <- rp + return +} + +func (e *a1Receiver) Run() { + // Set MDC (read: name visible in the logs) + xapp.Logger.SetMdc(handlerID, "0.1.0") + + /* from reading the xapp frame code... + this SetReadyCB sets off a chain of events.. + it sets readycb and readycbparams at the module level in xapp.go + nothing happens yet.. + when the xapp is ran with` xapp.Run, this callback actually gets passed into the Rmr client which is not exposed in the xapp + Rmr.SetReadyCB(xappReadyCb, nil) + This "primes" the rmr client with it's own readycb, which is now set to this callback function + When the rmr client is ready, it invokes the callback + so basically, when rmr is ready, this function is invoked + I think the xapp frame code could have been greatly simplified by just passing this into the invocation of Run() and then just passing that into the rmr client init! + */ + xapp.SetReadyCB(func(d interface{}) { e.rmrReady = true }, true) + + // start message loop. We cannot wait for e.rmrReady here since that doesn't get populated until Run() runs. + go e.messageLoop() + + if doQuery { + // we are in the query tester; kick off a loop that does that until it works + go e.sendQuery() + } + + xapp.Run(e) +} + +func newA1Receiver(appReady, rmrReady bool) *a1Receiver { + return &a1Receiver{ + msgChan: make(chan *xapp.RMRParams), + rmrReady: rmrReady, + appReady: appReady, + } +} + +func main() { + + delay = 0 + if d, ok := os.LookupEnv("TEST_RCV_SEC_DELAY"); ok { + delay, _ = strconv.Atoi(d) + } + + handlerID = "test_receiver" + if hid, ok := os.LookupEnv("HANDLER_ID"); ok { + handlerID = hid + } + + doQuery = false + if _, ok := os.LookupEnv("DO_QUERY"); ok { + doQuery = true + } + + newA1Receiver(true, false).Run() +} diff --git a/integration_tests/testxappcode/test-config-file.yaml b/integration_tests/testxappcode/test-config-file.yaml new file mode 100644 index 0000000..cd59770 --- /dev/null +++ b/integration_tests/testxappcode/test-config-file.yaml @@ -0,0 +1,38 @@ +# Copyright (c) 2019-2020 AT&T Intellectual Property. +# Copyright (c) 2019-2020 Nokia. +# +# 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. + +"local": + "host": ":8080" +"logger": + "level": 4 +"rmr": + "protPort": "tcp:4560" + "maxSize": 4096 + "numWorkers": 1 +"db": + "host": "dbaas" + "port": 6379 + "namespaces": ["sdl", "rnib"] +"test": + "mode": "forwarder" + "mtype": 10004 + "subId": 1111 + "size": 100 + "rate": 10 + "amount": 10 + "rounds": 1 + "store": 0 + "waitForAck": 0 + diff --git a/local.rt b/local.rt new file mode 100644 index 0000000..02816b5 --- /dev/null +++ b/local.rt @@ -0,0 +1,4 @@ +# Trivial RMR route table +newrt | start +rte | 1 | app10:4560 +newrt | end -- 2.16.6