Adding back files from python version needed from testing.
Signed-off-by: naman.gupta <naman.gupta@samsung.com>
Change-Id: I42b5c87c41a2efc25ac1cd63bc53e969882de48d
--- /dev/null
+# 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
--- /dev/null
+# 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/
--- /dev/null
+[gerrit]
+host=gerrit.o-ran-sc.org
+port=29418
+project=ric-plt/a1/
+defaultbranch=master
--- /dev/null
+# 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/
--- /dev/null
+apiVersion: v1
+description: A1 Helm chart for Kubernetes
+name: a1mediator
+version: 2.2.0
--- /dev/null
+{{/* 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 -}}
--- /dev/null
+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
--- /dev/null
+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"
--- /dev/null
+{{- define "imagePullSecret" }}
+{{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.imageCredentials.registry (printf "%s:%s" .Values.imageCredentials.username .Values.imageCredentials.password | b64enc) | b64enc }}
+{{- end }}
--- /dev/null
+# 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 }}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+# 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
--- /dev/null
+This was stolen from https://gerrit.o-ran-sc.org/r/gitweb?p=ric-plt/dbaas.git
--- /dev/null
+# 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
--- /dev/null
+# 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 }}
--- /dev/null
+# 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
--- /dev/null
+#!/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
--- /dev/null
+#!/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 "<<<installing rmr devel headers>>>" \
+ && cmake .. -DDEV_PKG=1; make install \
+ && echo "<<< installing rmr .so>>>" \
+ && cmake .. -DPACK_EXTERNALS=1; sudo make install \
+ && echo "cleanup" \
+ && cd ../.. \
+ && rm -rf rmr
--- /dev/null
+#!/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 &
--- /dev/null
+# 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
--- /dev/null
+# 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/
--- /dev/null
+apiVersion: v1
+appVersion: "1.0"
+description: Test receiver for a1 integration tests
+name: testreceiver
+version: 0.1.0
--- /dev/null
+{{/* 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 -}}
--- /dev/null
+#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
--- /dev/null
+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"
--- /dev/null
+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 }}
--- /dev/null
+replicaCount: 1
+
+testrmrservice:
+ name: testreceiverrmrservice
+ type: ClusterIP
+ port: 4560
+
+delayrmrservice:
+ name: delayreceiverrmrservice
+ type: ClusterIP
+ port: 4563
+
+queryrmrservice:
+ name: queryreceiverrmrservice
+ type: ClusterIP
+ port: 4564
--- /dev/null
+# ==================================================================================
+# 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"]
--- /dev/null
+# ==================================================================================
+# 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"]
--- /dev/null
+# ==================================================================================
+# 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"]
--- /dev/null
+# 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
+
--- /dev/null
+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
--- /dev/null
+# 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
+
--- /dev/null
+/*
+==================================================================================
+ 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()
+}
--- /dev/null
+# 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
+
--- /dev/null
+# Trivial RMR route table
+newrt | start
+rte | 1 | app10:4560
+newrt | end