Charm cleanup 96/12996/4
authorMark Beierl <mark.beierl@canonical.com>
Wed, 22 Feb 2023 18:00:58 +0000 (13:00 -0500)
committerbeierlm <mark.beierl@canonical.com>
Tue, 7 Mar 2023 19:49:02 +0000 (20:49 +0100)
Removal of obsolete charm code

Change-Id: Ifc5e83457cf580d8b236a636328470c527c5c3a9
Signed-off-by: Mark Beierl <mark.beierl@canonical.com>
132 files changed:
devops-stages/stage-test.sh
installers/charm/build.sh [deleted file]
installers/charm/interfaces/keystone/interface.yaml [deleted file]
installers/charm/interfaces/keystone/provides.py [deleted file]
installers/charm/interfaces/keystone/requires.py [deleted file]
installers/charm/interfaces/osm-nbi/README.md [deleted file]
installers/charm/interfaces/osm-nbi/copyright [deleted file]
installers/charm/interfaces/osm-nbi/interface.yaml [deleted file]
installers/charm/interfaces/osm-nbi/provides.py [deleted file]
installers/charm/interfaces/osm-nbi/requires.py [deleted file]
installers/charm/interfaces/osm-ro/README.md [deleted file]
installers/charm/interfaces/osm-ro/copyright [deleted file]
installers/charm/interfaces/osm-ro/interface.yaml [deleted file]
installers/charm/interfaces/osm-ro/provides.py [deleted file]
installers/charm/interfaces/osm-ro/requires.py [deleted file]
installers/charm/layers/osm-common/README.md [deleted file]
installers/charm/layers/osm-common/layer.yaml [deleted file]
installers/charm/layers/osm-common/lib/charms/osm/k8s.py [deleted file]
installers/charm/layers/osm-common/metadata.yaml [deleted file]
installers/charm/layers/osm-common/reactive/osm_common.py [deleted file]
installers/charm/lcm/.gitignore [deleted file]
installers/charm/lcm/.jujuignore [deleted file]
installers/charm/lcm/.yamllint.yaml [deleted file]
installers/charm/lcm/README.md [deleted file]
installers/charm/lcm/charmcraft.yaml [deleted file]
installers/charm/lcm/config.yaml [deleted file]
installers/charm/lcm/lib/charms/kafka_k8s/v0/kafka.py [deleted file]
installers/charm/lcm/metadata.yaml [deleted file]
installers/charm/lcm/requirements-test.txt [deleted file]
installers/charm/lcm/requirements.txt [deleted file]
installers/charm/lcm/src/charm.py [deleted file]
installers/charm/lcm/src/pod_spec.py [deleted file]
installers/charm/lcm/tests/__init__.py [deleted file]
installers/charm/lcm/tests/test_charm.py [deleted file]
installers/charm/lcm/tests/test_pod_spec.py [deleted file]
installers/charm/lcm/tox.ini [deleted file]
installers/charm/lint.sh [deleted file]
installers/charm/mon/.gitignore [deleted file]
installers/charm/mon/.jujuignore [deleted file]
installers/charm/mon/.yamllint.yaml [deleted file]
installers/charm/mon/README.md [deleted file]
installers/charm/mon/charmcraft.yaml [deleted file]
installers/charm/mon/config.yaml [deleted file]
installers/charm/mon/lib/charms/kafka_k8s/v0/kafka.py [deleted file]
installers/charm/mon/metadata.yaml [deleted file]
installers/charm/mon/requirements-test.txt [deleted file]
installers/charm/mon/requirements.txt [deleted file]
installers/charm/mon/src/charm.py [deleted file]
installers/charm/mon/src/pod_spec.py [deleted file]
installers/charm/mon/tests/__init__.py [deleted file]
installers/charm/mon/tests/test_charm.py [deleted file]
installers/charm/mon/tests/test_pod_spec.py [deleted file]
installers/charm/mon/tox.ini [deleted file]
installers/charm/nbi/.gitignore [deleted file]
installers/charm/nbi/.jujuignore [deleted file]
installers/charm/nbi/.yamllint.yaml [deleted file]
installers/charm/nbi/README.md [deleted file]
installers/charm/nbi/charmcraft.yaml [deleted file]
installers/charm/nbi/config.yaml [deleted file]
installers/charm/nbi/lib/charms/kafka_k8s/v0/kafka.py [deleted file]
installers/charm/nbi/metadata.yaml [deleted file]
installers/charm/nbi/requirements-test.txt [deleted file]
installers/charm/nbi/requirements.txt [deleted file]
installers/charm/nbi/src/charm.py [deleted file]
installers/charm/nbi/src/pod_spec.py [deleted file]
installers/charm/nbi/tests/__init__.py [deleted file]
installers/charm/nbi/tests/test_charm.py [deleted file]
installers/charm/nbi/tests/test_pod_spec.py [deleted file]
installers/charm/nbi/tox.ini [deleted file]
installers/charm/ng-ui/.gitignore [deleted file]
installers/charm/ng-ui/.jujuignore [deleted file]
installers/charm/ng-ui/.yamllint.yaml [deleted file]
installers/charm/ng-ui/README.md [deleted file]
installers/charm/ng-ui/charmcraft.yaml [deleted file]
installers/charm/ng-ui/config.yaml [deleted file]
installers/charm/ng-ui/metadata.yaml [deleted file]
installers/charm/ng-ui/requirements-test.txt [deleted file]
installers/charm/ng-ui/requirements.txt [deleted file]
installers/charm/ng-ui/src/charm.py [deleted file]
installers/charm/ng-ui/src/pod_spec.py [deleted file]
installers/charm/ng-ui/templates/default.template [deleted file]
installers/charm/ng-ui/tests/__init__.py [deleted file]
installers/charm/ng-ui/tests/test_charm.py [deleted file]
installers/charm/ng-ui/tox.ini [deleted file]
installers/charm/pla/.gitignore [deleted file]
installers/charm/pla/.jujuignore [deleted file]
installers/charm/pla/.yamllint.yaml [deleted file]
installers/charm/pla/README.md [deleted file]
installers/charm/pla/charmcraft.yaml [deleted file]
installers/charm/pla/config.yaml [deleted file]
installers/charm/pla/lib/charms/kafka_k8s/v0/kafka.py [deleted file]
installers/charm/pla/metadata.yaml [deleted file]
installers/charm/pla/requirements-test.txt [deleted file]
installers/charm/pla/requirements.txt [deleted file]
installers/charm/pla/src/charm.py [deleted file]
installers/charm/pla/tests/__init__.py [deleted file]
installers/charm/pla/tests/test_charm.py [deleted file]
installers/charm/pla/tox.ini [deleted file]
installers/charm/pol/.gitignore [deleted file]
installers/charm/pol/.jujuignore [deleted file]
installers/charm/pol/.yamllint.yaml [deleted file]
installers/charm/pol/README.md [deleted file]
installers/charm/pol/charmcraft.yaml [deleted file]
installers/charm/pol/config.yaml [deleted file]
installers/charm/pol/lib/charms/kafka_k8s/v0/kafka.py [deleted file]
installers/charm/pol/metadata.yaml [deleted file]
installers/charm/pol/requirements-test.txt [deleted file]
installers/charm/pol/requirements.txt [deleted file]
installers/charm/pol/src/charm.py [deleted file]
installers/charm/pol/src/pod_spec.py [deleted file]
installers/charm/pol/tests/__init__.py [deleted file]
installers/charm/pol/tests/test_charm.py [deleted file]
installers/charm/pol/tests/test_pod_spec.py [deleted file]
installers/charm/pol/tox.ini [deleted file]
installers/charm/release_edge.sh [deleted file]
installers/charm/ro/.gitignore [deleted file]
installers/charm/ro/.jujuignore [deleted file]
installers/charm/ro/.yamllint.yaml [deleted file]
installers/charm/ro/README.md [deleted file]
installers/charm/ro/charmcraft.yaml [deleted file]
installers/charm/ro/config.yaml [deleted file]
installers/charm/ro/lib/charms/kafka_k8s/v0/kafka.py [deleted file]
installers/charm/ro/metadata.yaml [deleted file]
installers/charm/ro/requirements-test.txt [deleted file]
installers/charm/ro/requirements.txt [deleted file]
installers/charm/ro/src/charm.py [deleted file]
installers/charm/ro/src/pod_spec.py [deleted file]
installers/charm/ro/tests/__init__.py [deleted file]
installers/charm/ro/tests/test_charm.py [deleted file]
installers/charm/ro/tests/test_pod_spec.py [deleted file]
installers/charm/ro/tox.ini [deleted file]
installers/charm/update-bundle-revisions.sh [deleted file]

index b455932..b37ca5c 100755 (executable)
@@ -24,7 +24,7 @@ CURRENT_DIR=`pwd`
 
 # Execute tests for charms
 CHARM_PATH="./installers/charm"
-CHARM_NAMES="keystone lcm mon nbi ng-ui pla pol prometheus ro grafana mongodb-exporter mysqld-exporter kafka-exporter"
+CHARM_NAMES="keystone prometheus grafana"
 for charm in $CHARM_NAMES; do
     cd $CHARM_PATH/$charm
     TOX_PARALLEL_NO_SPINNER=1 tox --parallel=auto
diff --git a/installers/charm/build.sh b/installers/charm/build.sh
deleted file mode 100755 (executable)
index 459da13..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-
-function build() {
-    cd $1 && tox -qe build && cd ..
-}
-
-charms="ro nbi pla pol mon lcm ng-ui grafana prometheus mongodb-exporter kafka-exporter mysqld-exporter"
-if [ -z `which charmcraft` ]; then
-    sudo snap install charmcraft --classic
-fi
-
-for charm_directory in $charms; do
-    build $charm_directory
-done
-wait
\ No newline at end of file
diff --git a/installers/charm/interfaces/keystone/interface.yaml b/installers/charm/interfaces/keystone/interface.yaml
deleted file mode 100644 (file)
index be1d09b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-name: keystone
-summary: Keystone Interface
-version: 1
diff --git a/installers/charm/interfaces/keystone/provides.py b/installers/charm/interfaces/keystone/provides.py
deleted file mode 100644 (file)
index bda5d2f..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-from charms.reactive import Endpoint
-from charms.reactive import when
-from charms.reactive import set_flag, clear_flag
-
-
-class KeystoneProvides(Endpoint):
-    @when("endpoint.{endpoint_name}.joined")
-    def _joined(self):
-        set_flag(self.expand_name("{endpoint_name}.joined"))
-
-    @when("endpoint.{endpoint_name}.changed")
-    def _changed(self):
-        set_flag(self.expand_name("{endpoint_name}.ready"))
-
-    @when("endpoint.{endpoint_name}.departed")
-    def _departed(self):
-        set_flag(self.expand_name("{endpoint_name}.departed"))
-        clear_flag(self.expand_name("{endpoint_name}.joined"))
-
-    def publish_info(
-        self,
-        host,
-        port,
-        keystone_db_password,
-        region_id,
-        user_domain_name,
-        project_domain_name,
-        admin_username,
-        admin_password,
-        admin_project_name,
-        username,
-        password,
-        service,
-    ):
-        for relation in self.relations:
-            relation.to_publish["host"] = host
-            relation.to_publish["port"] = port
-            relation.to_publish["keystone_db_password"] = keystone_db_password
-            relation.to_publish["region_id"] = region_id
-            relation.to_publish["user_domain_name"] = user_domain_name
-            relation.to_publish["project_domain_name"] = project_domain_name
-            relation.to_publish["admin_username"] = admin_username
-            relation.to_publish["admin_password"] = admin_password
-            relation.to_publish["admin_project_name"] = admin_project_name
-            relation.to_publish["username"] = username
-            relation.to_publish["password"] = password
-            relation.to_publish["service"] = service
-
-    def mark_complete(self):
-        clear_flag(self.expand_name("{endpoint_name}.joined"))
diff --git a/installers/charm/interfaces/keystone/requires.py b/installers/charm/interfaces/keystone/requires.py
deleted file mode 100644 (file)
index c0d8d47..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-from charms.reactive import Endpoint
-from charms.reactive import when
-from charms.reactive import set_flag, clear_flag
-
-
-class KeystoneRequires(Endpoint):
-    @when("endpoint.{endpoint_name}.joined")
-    def _joined(self):
-        set_flag(self.expand_name("{endpoint_name}.joined"))
-
-    @when("endpoint.{endpoint_name}.changed")
-    def _changed(self):
-        if len(self.keystones()) > 0:
-            set_flag(self.expand_name("{endpoint_name}.ready"))
-        else:
-            clear_flag(self.expand_name("{endpoint_name}.ready"))
-
-    @when("endpoint.{endpoint_name}.departed")
-    def _departed(self):
-        set_flag(self.expand_name("{endpoint_name}.departed"))
-        clear_flag(self.expand_name("{endpoint_name}.joined"))
-        clear_flag(self.expand_name("{endpoint_name}.ready"))
-
-    def keystones(self):
-        """
-        Return Keystone Data:
-        [{
-            'host': <host>,
-            'port': <port>,
-            'keystone_db_password: <keystone_db_password>,
-            'region_id: <region_id>,
-            'admin_username: <admin_username>,
-            'admin_password: <admin_password>,
-            'admin_project_name: <admin_project_name>,
-            'username: <username>,
-            'password: <password>,
-            'service: <service>
-        }]
-        """
-        keystones = []
-        for relation in self.relations:
-            for unit in relation.units:
-                data = {
-                    "host": unit.received["host"],
-                    "port": unit.received["port"],
-                    "keystone_db_password": unit.received["keystone_db_password"],
-                    "region_id": unit.received["region_id"],
-                    "user_domain_name": unit.received["user_domain_name"],
-                    "project_domain_name": unit.received["project_domain_name"],
-                    "admin_username": unit.received["admin_username"],
-                    "admin_password": unit.received["admin_password"],
-                    "admin_project_name": unit.received["admin_project_name"],
-                    "username": unit.received["username"],
-                    "password": unit.received["password"],
-                    "service": unit.received["service"],
-                }
-                if all(data.values()):
-                    keystones.append(data)
-        return keystones
diff --git a/installers/charm/interfaces/osm-nbi/README.md b/installers/charm/interfaces/osm-nbi/README.md
deleted file mode 100644 (file)
index 8fb9523..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<!--
-Copyright 2020 Canonical Ltd.
-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. -->
-
-# Overview
-
-This interface layer handles communication between Mongodb and its clients.
-
-## Usage
-
-### Provides
-
-To implement this relation to offer an nbi:
-
-In your charm's metadata.yaml:
-
-```yaml
-provides:
-    nbi:
-        interface: osm-nbi
-```
-
-reactive/mynbi.py:
-
-```python
-@when('nbi.joined')
-def send_config(nbi):
-    nbi.send_connection(
-        unit_get('private-address'),
-        get_nbi_port()
-    )
-```
-
-### Requires
-
-If you would like to use an nbi from your charm:
-
-metadata.yaml:
-
-```yaml
-requires:
-    nbi:
-        interface: osm-nbi
-```
-
-reactive/mycharm.py:
-
-```python
-@when('nbi.ready')
-def nbi_ready():
-    nbi = endpoint_from_flag('nbi.ready')
-    if nbi:
-        for unit in nbi.nbis():
-            add_nbi(unit['host'], unit['port'])
-```
diff --git a/installers/charm/interfaces/osm-nbi/copyright b/installers/charm/interfaces/osm-nbi/copyright
deleted file mode 100644 (file)
index dd9405e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Format: http://dep.debian.net/deps/dep5/
-
-Files: *
-Copyright: Copyright 2020, Canonical Ltd., All Rights Reserved.
-License: Apache License 2.0
- 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.
\ No newline at end of file
diff --git a/installers/charm/interfaces/osm-nbi/interface.yaml b/installers/charm/interfaces/osm-nbi/interface.yaml
deleted file mode 100644 (file)
index ec8ee86..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-name: osm-nbi
-summary: Interface for relating to a OSM Northbound Interface
-maintainer: '"Adam Israel" <adam@adamisrael.com>'
diff --git a/installers/charm/interfaces/osm-nbi/provides.py b/installers/charm/interfaces/osm-nbi/provides.py
deleted file mode 100644 (file)
index 7ff3199..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-
-from charms.reactive import RelationBase
-from charms.reactive import hook
-from charms.reactive import scopes
-
-
-class OsmNBIProvides(RelationBase):
-    scope = scopes.GLOBAL
-
-    @hook("{provides:osm-nbi}-relation-joined")
-    def joined(self):
-        self.set_state("{relation_name}.joined")
-
-    @hook("{provides:osm-nbi}-relation-changed")
-    def changed(self):
-        self.set_state("{relation_name}.ready")
-
-    @hook("{provides:osm-nbi}-relation-{broken,departed}")
-    def broken_departed(self):
-        self.remove_state("{relation_name}.ready")
-        self.remove_state("{relation_name}.joined")
-
-    @hook("{provides:osm-nbi}-relation-broken")
-    def broken(self):
-        self.set_state("{relation_name}.removed")
-
-    def send_connection(self, host, port=9999):
-        conv = self.conversation()
-        conv.set_remote("host", host)
-        conv.set_remote("port", port)
diff --git a/installers/charm/interfaces/osm-nbi/requires.py b/installers/charm/interfaces/osm-nbi/requires.py
deleted file mode 100644 (file)
index a5e8e29..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-
-from charms.reactive import RelationBase
-from charms.reactive import hook
-from charms.reactive import scopes
-
-
-class OsmNBIRequires(RelationBase):
-    scope = scopes.GLOBAL
-
-    @hook("{requires:osm-nbi}-relation-joined")
-    def joined(self):
-        conv = self.conversation()
-        conv.set_state("{relation_name}.joined")
-
-    @hook("{requires:osm-nbi}-relation-changed")
-    def changed(self):
-        conv = self.conversation()
-        if self.nbis():
-            conv.set_state("{relation_name}.ready")
-        else:
-            conv.remove_state("{relation_name}.ready")
-
-    @hook("{requires:osm-nbi}-relation-departed")
-    def departed(self):
-        conv = self.conversation()
-        conv.remove_state("{relation_name}.ready")
-        conv.remove_state("{relation_name}.joined")
-
-    def nbis(self):
-        """Return the NBI's host and port.
-
-        [{
-            'host': <host>,
-            'port': <port>,
-        }]
-        """
-        nbis = []
-        for conv in self.conversations():
-            port = conv.get_remote("port")
-            host = conv.get_remote("host") or conv.get_remote("private-address")
-            if host and port:
-                nbis.append({"host": host, "port": port})
-        return nbis
diff --git a/installers/charm/interfaces/osm-ro/README.md b/installers/charm/interfaces/osm-ro/README.md
deleted file mode 100644 (file)
index eb6413a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<!--
-Copyright 2020 Canonical Ltd.
-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. -->
-
-# Overview
-
-This interface layer handles communication between OSM's RO and its clients.
-
-## Usage
-
-### Provides
-
-To implement this relation to offer an ro:
-
-In your charm's metadata.yaml:
-
-```yaml
-provides:
-    ro:
-        interface: osm-ro
-```
-
-reactive/myro.py:
-
-```python
-@when('ro.joined')
-def send_config(ro):
-    ro.send_connection(
-        unit_get('private-address'),
-        get_ro_port()
-    )
-```
-
-### Requires
-
-If you would like to use a rodb from your charm:
-
-metadata.yaml:
-
-```yaml
-requires:
-    ro:
-        interface: osm-ro
-```
-
-reactive/mycharm.py:
-
-```python
-@when('ro.ready')
-def ro_ready():
-    ro = endpoint_from_flag('ro.ready')
-    if ro:
-        for unit in ro.ros():
-            add_ro(unit['host'], unit['port'])
-```
diff --git a/installers/charm/interfaces/osm-ro/copyright b/installers/charm/interfaces/osm-ro/copyright
deleted file mode 100644 (file)
index 9270d6c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-Format: http://dep.debian.net/deps/dep5/
-
-Files: *
-Copyright: Copyright 2020, Canonical Ltd., All Rights Reserved.
-License: Apache License 2.0
- 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.
diff --git a/installers/charm/interfaces/osm-ro/interface.yaml b/installers/charm/interfaces/osm-ro/interface.yaml
deleted file mode 100644 (file)
index 9a12872..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-name: osm-ro
-summary: Interface for relating to a OSM Resource Orchestrator
-maintainer: '"Adam Israel" <adam@adamisrael.com>'
diff --git a/installers/charm/interfaces/osm-ro/provides.py b/installers/charm/interfaces/osm-ro/provides.py
deleted file mode 100644 (file)
index f577319..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-
-from charms.reactive import RelationBase
-from charms.reactive import hook
-from charms.reactive import scopes
-
-
-class OsmROProvides(RelationBase):
-    scope = scopes.GLOBAL
-
-    @hook("{provides:osm-ro}-relation-joined")
-    def joined(self):
-        self.set_state("{relation_name}.joined")
-
-    @hook("{provides:osm-ro}-relation-changed")
-    def changed(self):
-        self.set_state("{relation_name}.ready")
-
-    @hook("{provides:osm-ro}-relation-{broken,departed}")
-    def broken_departed(self):
-        self.remove_state("{relation_name}.ready")
-        self.remove_state("{relation_name}.joined")
-
-    @hook("{provides:osm-ro}-relation-broken")
-    def broken(self):
-        self.set_state("{relation_name}.removed")
-
-    def send_connection(self, host, port=9090):
-        conv = self.conversation()
-        conv.set_remote("host", host)
-        conv.set_remote("port", port)
diff --git a/installers/charm/interfaces/osm-ro/requires.py b/installers/charm/interfaces/osm-ro/requires.py
deleted file mode 100644 (file)
index fc8f0f4..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-
-from charms.reactive import RelationBase
-from charms.reactive import hook
-from charms.reactive import scopes
-
-
-class OsmRORequires(RelationBase):
-    scope = scopes.GLOBAL
-
-    @hook("{requires:osm-ro}-relation-joined")
-    def joined(self):
-        conv = self.conversation()
-        conv.set_state("{relation_name}.joined")
-
-    @hook("{requires:osm-ro}-relation-changed")
-    def changed(self):
-        conv = self.conversation()
-        if self.ros():
-            conv.set_state("{relation_name}.ready")
-        else:
-            conv.remove_state("{relation_name}.ready")
-
-    @hook("{requires:osm-ro}-relation-departed")
-    def departed(self):
-        conv = self.conversation()
-        conv.remove_state("{relation_name}.ready")
-        conv.remove_state("{relation_name}.joined")
-
-    def ros(self):
-        """Return the NBI's host and port.
-
-        [{
-            'host': <host>,
-            'port': <port>,
-        }]
-        """
-        ros = []
-        for conv in self.conversations():
-            port = conv.get_remote("port")
-            host = conv.get_remote("host") or conv.get_remote("private-address")
-            if host and port:
-                ros.append({"host": host, "port": port})
-        return ros
diff --git a/installers/charm/layers/osm-common/README.md b/installers/charm/layers/osm-common/README.md
deleted file mode 100644 (file)
index c55b97b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- Copyright 2020 Canonical Ltd.
-
-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. -->
-
-# README
-
-WIP. Layer to share common functionality to write/deploy k8s charms for OSM demo
diff --git a/installers/charm/layers/osm-common/layer.yaml b/installers/charm/layers/osm-common/layer.yaml
deleted file mode 100644 (file)
index 6e8379a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
\ No newline at end of file
diff --git a/installers/charm/layers/osm-common/lib/charms/osm/k8s.py b/installers/charm/layers/osm-common/lib/charms/osm/k8s.py
deleted file mode 100644 (file)
index 9735517..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-
-from charmhelpers.core.hookenv import (
-    network_get,
-    relation_id,
-    log,
-)
-
-
-def get_service_ip(endpoint):
-    try:
-        info = network_get(endpoint, relation_id())
-        if 'ingress-addresses' in info:
-            addr = info['ingress-addresses'][0]
-            if len(addr):
-                return addr
-        else:
-            log("No ingress-addresses: {}".format(info))
-    except Exception as e:
-        log("Caught exception checking for service IP: {}".format(e))
-
-    return None
-
-
-def is_pod_up(endpoint):
-    """Check to see if the pod of a relation is up.
-
-    application-vimdb: 19:29:10 INFO unit.vimdb/0.juju-log network info
-
-    In the example below:
-    - 10.1.1.105 is the address of the application pod.
-    - 10.152.183.199 is the service cluster ip
-
-    {
-        'bind-addresses': [{
-            'macaddress': '',
-            'interfacename': '',
-            'addresses': [{
-                'hostname': '',
-                'address': '10.1.1.105',
-                'cidr': ''
-            }]
-        }],
-        'egress-subnets': [
-            '10.152.183.199/32'
-        ],
-        'ingress-addresses': [
-            '10.152.183.199',
-            '10.1.1.105'
-        ]
-    }
-    """
-    try:
-        info = network_get(endpoint, relation_id())
-
-        # Check to see if the pod has been assigned it's internal and
-        # external ips
-        for ingress in info['ingress-addresses']:
-            if len(ingress) == 0:
-                return False
-    except:
-        return False
-
-    return True
diff --git a/installers/charm/layers/osm-common/metadata.yaml b/installers/charm/layers/osm-common/metadata.yaml
deleted file mode 100644 (file)
index 6e8379a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
\ No newline at end of file
diff --git a/installers/charm/layers/osm-common/reactive/osm_common.py b/installers/charm/layers/osm-common/reactive/osm_common.py
deleted file mode 100644 (file)
index 6e8379a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
\ No newline at end of file
diff --git a/installers/charm/lcm/.gitignore b/installers/charm/lcm/.gitignore
deleted file mode 100644 (file)
index 2885df2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.stestr
-cover
-release
\ No newline at end of file
diff --git a/installers/charm/lcm/.jujuignore b/installers/charm/lcm/.jujuignore
deleted file mode 100644 (file)
index 3ae3e7d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.gitignore
-.stestr
-cover
-release
-tests/
-requirements*
-tox.ini
diff --git a/installers/charm/lcm/.yamllint.yaml b/installers/charm/lcm/.yamllint.yaml
deleted file mode 100644 (file)
index d71fb69..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
----
-extends: default
-
-yaml-files:
-  - "*.yaml"
-  - "*.yml"
-  - ".yamllint"
-ignore: |
-  .tox
-  cover/
-  build/
-  venv
-  release/
diff --git a/installers/charm/lcm/README.md b/installers/charm/lcm/README.md
deleted file mode 100644 (file)
index 1a6cd74..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<!-- Copyright 2020 Canonical Ltd.
-
-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.
-
-For those usages not covered by the Apache License, Version 2.0 please
-contact: legal@canonical.com
-
-To get in touch with the maintainers, please contact:
-osm-charmers@lists.launchpad.net -->
-
-# LCM operator Charm for Kubernetes
-
-## Requirements
diff --git a/installers/charm/lcm/charmcraft.yaml b/installers/charm/lcm/charmcraft.yaml
deleted file mode 100644 (file)
index 0a285a9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-type: charm
-bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: ["amd64"]
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-          - aarch64
-          - arm64
-parts:
-  charm:
-    build-packages: [git]
diff --git a/installers/charm/lcm/config.yaml b/installers/charm/lcm/config.yaml
deleted file mode 100644 (file)
index 709a8ca..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-options:
-  vca_host:
-    type: string
-    description: "The VCA host."
-  vca_port:
-    type: int
-    description: "The VCA port."
-  vca_user:
-    type: string
-    description: "The VCA user name."
-  vca_secret:
-    type: string
-    description: "The VCA user secret."
-  vca_pubkey:
-    type: string
-    description: "The VCA public key."
-  vca_cacert:
-    type: string
-    description: "The VCA cacert."
-  vca_apiproxy:
-    type: string
-    description: "The VCA api proxy (native charms)"
-  vca_cloud:
-    type: string
-    description: "The VCA lxd cloud name"
-  vca_k8s_cloud:
-    type: string
-    description: "The VCA K8s cloud name"
-  database_commonkey:
-    description: Database common key
-    type: string
-    default: osm
-  mongodb_uri:
-    type: string
-    description: MongoDB URI (external database)
-  log_level:
-    description: "Log Level"
-    type: string
-    default: "INFO"
-  vca_model_config_agent_metadata_url:
-    description: The URL of the private stream.
-    type: string
-  vca_model_config_agent_stream:
-    description: |
-      The stream to use for deploy/upgrades of agents.
-      See additional info below.
-    type: string
-  vca_model_config_apt_ftp_proxy:
-    description: The APT FTP proxy for the model.
-    type: string
-  vca_model_config_apt_http_proxy:
-    description: The APT HTTP proxy for the model.
-    type: string
-  vca_model_config_apt_https_proxy:
-    description: The APT HTTPS proxy for the model.
-    type: string
-  vca_model_config_apt_mirror:
-    description: The APT mirror for the model.
-    type: string
-  vca_model_config_apt_no_proxy:
-    description: The APT no proxy for the model.
-    type: string
-  vca_model_config_automatically_retry_hooks:
-    description: Set the policy on retying failed hooks.
-    type: boolean
-  vca_model_config_backup_dir:
-    description: Backup directory
-    type: string
-  vca_model_config_cloudinit_userdata:
-    description: Cloudinit userdata
-    type: string
-  vca_model_config_container_image_metadata_url:
-    description: |
-      Corresponds to 'image-metadata-url' (see below) for cloud-hosted
-      KVM guests or LXD containers. Not needed for the localhost cloud.
-    type: string
-  vca_model_config_container_image_stream:
-    description: |
-      Corresponds to 'image-stream' (see below) for cloud-hosted KVM
-      guests or LXD containers. Not needed for the localhost cloud.
-    type: string
-  vca_model_config_container_inherit_properties:
-    description: |
-      Set parameters to be inherited from a machine toits hosted
-      containers (KVM or LXD).
-    type: string
-  vca_model_config_container_networking_method:
-    description: |
-      The FAN networking mode to use. Default values can be provider-specific.
-    type: string
-  vca_model_config_default_series:
-    description: The default series of Ubuntu to use for deploying charms.
-    type: string
-  vca_model_config_default_space:
-    description: |
-      The space used as the default binding when deploying charms.
-      Will be "alpha" by default.
-    type: string
-  vca_model_config_development:
-    description: Set whether the model is in development mode.
-    type: boolean
-  vca_model_config_disable_network_management:
-    description: |
-      Set whether to give network control to the provider instead
-      of Juju controlling configuration.
-    type: boolean
-  vca_model_config_egress_subnets:
-    description: Egress subnets
-    type: string
-  vca_model_config_enable_os_refresh_update:
-    description: |
-      Set whether newly provisioned instances should run their
-      respective OS's update capability.
-    type: boolean
-  vca_model_config_enable_os_upgrade:
-    description: |
-      Set whether newly provisioned instances should run their
-      respective OS's upgrade capability.
-    type: boolean
-  vca_model_config_fan_config:
-    description: |
-      The FAN overlay and underlay networks in
-      CIDR notation (space-separated).
-    type: string
-  vca_model_config_firewall_mode:
-    description: The mode to use for network firewalling.
-    type: string
-  vca_model_config_ftp_proxy:
-    description: |
-      The FTP proxy value to configure on instances,
-      in the FTP_PROXY environment variable.
-    type: string
-  vca_model_config_http_proxy:
-    description: |
-      The HTTP proxy value to configure on instances,
-      in the HTTP_PROXY environment variable.
-    type: string
-  vca_model_config_https_proxy:
-    description: |
-      The HTTPS proxy value to configure on instances,
-      in the HTTPS_PROXY environment variable.
-    type: string
-  vca_model_config_ignore_machine_addresses:
-    description: |
-      When true, the machine worker will not look up
-      or discover any machine addresses.
-    type: boolean
-  vca_model_config_image_metadata_url:
-    description: |
-      The URL at which the metadata used to locate
-      OS image ids is located.
-    type: string
-  vca_model_config_image_stream:
-    description: |
-      The simplestreams stream used to identify which image
-      ids to search when starting an instance.
-    type: string
-  vca_model_config_juju_ftp_proxy:
-    description: The charm-centric FTP proxy value.
-    type: string
-  vca_model_config_juju_http_proxy:
-    description: The charm-centric HTTP proxy value.
-    type: string
-  vca_model_config_juju_https_proxy:
-    description: The charm-centric HTTPS proxy value.
-    type: string
-  vca_model_config_juju_no_proxy:
-    description: The charm-centric no-proxy value.
-    type: string
-  vca_model_config_logforward_enabled:
-    description: Set whether the log forward function is enabled.
-    type: boolean
-  vca_model_config_logging_config:
-    description: |
-      The configuration string to use when configuring Juju agent logging
-    type: string
-  vca_model_config_lxd_snap_channel:
-    description: LXD snap channel
-    type: string
-  vca_model_config_max_action_results_age:
-    description: The maximum aget for status action results entries
-    type: string
-  vca_model_config_max_action_results_size:
-    description: The maximum size for status action results entries
-    type: string
-  vca_model_config_max_status_history_age:
-    description: |
-      The maximum age for status history entries before they are pruned,
-      in a human-readable time format.
-    type: string
-  vca_model_config_max_status_history_size:
-    description: |
-      The maximum size for the status history collection,
-      in human-readable memory format.
-    type: string
-  vca_model_config_net_bond_reconfigure_delay:
-    description: Net bond reconfigure delay
-    type: int
-  vca_model_config_no_proxy:
-    description: List of domain addresses not to be proxied (comma-separated).
-    type: string
-  vca_model_config_provisioner_harvest_mode:
-    description: Set what to do with unknown machines.
-    type: string
-  vca_model_config_proxy_ssh:
-    description: |
-      Set whether SSH commands should be proxied through the API server.
-    type: boolean
-  vca_model_config_snap_http_proxy:
-    description: The snap-centric HTTP proxy value.
-    type: string
-  vca_model_config_snap_https_proxy:
-    description: The snap-centric HTTPS proxy value.
-    type: string
-  vca_model_config_snap_store_assertions:
-    description: |
-      The collection of snap store assertions.
-      Each entry should contain the snap store ID.
-    type: string
-  vca_model_config_snap_store_proxy:
-    description: The snap store ID.
-    type: string
-  vca_model_config_snap_store_proxy_url:
-    description: The snap store proxy url
-    type: string
-  vca_model_config_ssl_hostname_verification:
-    description: Set whether SSL hostname verification is enabled.
-    type: boolean
-  vca_model_config_test_mode:
-    description: |
-      Set whether the model is intended for testing.
-      If true, accessing the charm store does not affect
-      statistical data of the store.
-    type: boolean
-  vca_model_config_transmit_vendor_metrics:
-    description: |
-      Set whether the controller will send metrics collected from
-      this model for use in anonymized aggregate analytics.
-    type: boolean
-  vca_model_config_update_status_hook_interval:
-    description: |
-      The run frequency of the update-status hook.
-      The value has a random +/- 20% offset applied to avoid hooks
-      for all units firing at once. Value change only honoured
-      during controller and model creation
-      (bootstrap --config and add-model --config).
-    type: string
-  vca_stablerepourl:
-    description: Stable repository URL for Helm charts
-    type: string
-    default: https://charts.helm.sh/stable
-  vca_helm_ca_certs:
-    description: CA certificates to validate access to Helm repository
-    type: string
-    default: ""
-  image_pull_policy:
-    type: string
-    description: |
-      ImagePullPolicy configuration for the pod.
-      Possible values: always, ifnotpresent, never
-    default: always
-  debug_mode:
-    description: |
-      If true, debug mode is activated. It means that the service will not run,
-      and instead, the command for the container will be a `sleep infinity`.
-      Note: If enabled, security_context will be disabled.
-    type: boolean
-    default: false
-  debug_pubkey:
-    description: |
-      Public SSH key that will be injected to the application pod.
-    type: string
-  debug_lcm_local_path:
-    description: |
-      Local full path to the LCM project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  debug_n2vc_local_path:
-    description: |
-      Local full path to the N2VC project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  debug_common_local_path:
-    description: |
-      Local full path to the COMMON project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  security_context:
-    description: Enables the security context of the pods
-    type: boolean
-    default: false
diff --git a/installers/charm/lcm/lib/charms/kafka_k8s/v0/kafka.py b/installers/charm/lcm/lib/charms/kafka_k8s/v0/kafka.py
deleted file mode 100644 (file)
index 1baf9a8..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2022 Canonical Ltd.
-# See LICENSE file for licensing details.
-#
-# 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.
-
-"""Kafka library.
-
-This [library](https://juju.is/docs/sdk/libraries) implements both sides of the
-`kafka` [interface](https://juju.is/docs/sdk/relations).
-
-The *provider* side of this interface is implemented by the
-[kafka-k8s Charmed Operator](https://charmhub.io/kafka-k8s).
-
-Any Charmed Operator that *requires* Kafka for providing its
-service should implement the *requirer* side of this interface.
-
-In a nutshell using this library to implement a Charmed Operator *requiring*
-Kafka would look like
-
-```
-$ charmcraft fetch-lib charms.kafka_k8s.v0.kafka
-```
-
-`metadata.yaml`:
-
-```
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-```
-
-`src/charm.py`:
-
-```
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.charm import CharmBase
-
-
-class MyCharm(CharmBase):
-
-    on = KafkaEvents()
-
-    def __init__(self, *args):
-        super().__init__(*args)
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(
-            self.on.kafka_available,
-            self._on_kafka_available,
-        )
-        self.framework.observe(
-            self.on.kafka_broken,
-            self._on_kafka_broken,
-        )
-
-    def _on_kafka_available(self, event):
-        # Get Kafka host and port
-        host: str = self.kafka.host
-        port: int = self.kafka.port
-        # host => "kafka-k8s"
-        # port => 9092
-
-    def _on_kafka_broken(self, event):
-        # Stop service
-        # ...
-        self.unit.status = BlockedStatus("need kafka relation")
-```
-
-You can file bugs
-[here](https://github.com/charmed-osm/kafka-k8s-operator/issues)!
-"""
-
-from typing import Optional
-
-from ops.charm import CharmBase, CharmEvents
-from ops.framework import EventBase, EventSource, Object
-
-# The unique Charmhub library identifier, never change it
-from ops.model import Relation
-
-LIBID = "eacc8c85082347c9aae740e0220b8376"
-
-# Increment this major API version when introducing breaking changes
-LIBAPI = 0
-
-# Increment this PATCH version before using `charmcraft publish-lib` or reset
-# to 0 if you are raising the major API version
-LIBPATCH = 3
-
-
-KAFKA_HOST_APP_KEY = "host"
-KAFKA_PORT_APP_KEY = "port"
-
-
-class _KafkaAvailableEvent(EventBase):
-    """Event emitted when Kafka is available."""
-
-
-class _KafkaBrokenEvent(EventBase):
-    """Event emitted when Kafka relation is broken."""
-
-
-class KafkaEvents(CharmEvents):
-    """Kafka events.
-
-    This class defines the events that Kafka can emit.
-
-    Events:
-        kafka_available (_KafkaAvailableEvent)
-    """
-
-    kafka_available = EventSource(_KafkaAvailableEvent)
-    kafka_broken = EventSource(_KafkaBrokenEvent)
-
-
-class KafkaRequires(Object):
-    """Requires-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self.charm = charm
-        self._endpoint_name = endpoint_name
-
-        # Observe relation events
-        event_observe_mapping = {
-            charm.on[self._endpoint_name].relation_changed: self._on_relation_changed,
-            charm.on[self._endpoint_name].relation_broken: self._on_relation_broken,
-        }
-        for event, observer in event_observe_mapping.items():
-            self.framework.observe(event, observer)
-
-    def _on_relation_changed(self, event) -> None:
-        if event.relation.app and all(
-            key in event.relation.data[event.relation.app]
-            for key in (KAFKA_HOST_APP_KEY, KAFKA_PORT_APP_KEY)
-        ):
-            self.charm.on.kafka_available.emit()
-
-    def _on_relation_broken(self, _) -> None:
-        self.charm.on.kafka_broken.emit()
-
-    @property
-    def host(self) -> str:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            relation.data[relation.app].get(KAFKA_HOST_APP_KEY)
-            if relation and relation.app
-            else None
-        )
-
-    @property
-    def port(self) -> int:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            int(relation.data[relation.app].get(KAFKA_PORT_APP_KEY))
-            if relation and relation.app
-            else None
-        )
-
-
-class KafkaProvides(Object):
-    """Provides-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self._endpoint_name = endpoint_name
-
-    def set_host_info(self, host: str, port: int, relation: Optional[Relation] = None) -> None:
-        """Set Kafka host and port.
-
-        This function writes in the application data of the relation, therefore,
-        only the unit leader can call it.
-
-        Args:
-            host (str): Kafka hostname or IP address.
-            port (int): Kafka port.
-            relation (Optional[Relation]): Relation to update.
-                                           If not specified, all relations will be updated.
-
-        Raises:
-            Exception: if a non-leader unit calls this function.
-        """
-        if not self.model.unit.is_leader():
-            raise Exception("only the leader set host information.")
-
-        if relation:
-            self._update_relation_data(host, port, relation)
-            return
-
-        for relation in self.model.relations[self._endpoint_name]:
-            self._update_relation_data(host, port, relation)
-
-    def _update_relation_data(self, host: str, port: int, relation: Relation) -> None:
-        """Update data in relation if needed."""
-        relation.data[self.model.app][KAFKA_HOST_APP_KEY] = host
-        relation.data[self.model.app][KAFKA_PORT_APP_KEY] = str(port)
diff --git a/installers/charm/lcm/metadata.yaml b/installers/charm/lcm/metadata.yaml
deleted file mode 100644 (file)
index e81cdd9..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-name: osm-lcm
-summary: OSM Lifecycle Management (LCM)
-description: |
-  A CAAS charm to deploy OSM's Lifecycle Management (LCM).
-series:
-  - kubernetes
-tags:
-  - kubernetes
-  - osm
-  - lcm
-min-juju-version: 2.8.0
-deployment:
-  type: stateless
-  service: cluster
-resources:
-  image:
-    type: oci-image
-    description: OSM docker image for LCM
-    upstream-source: "opensourcemano/lcm:latest"
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-  mongodb:
-    interface: mongodb
-    limit: 1
-  ro:
-    interface: http
-    limit: 1
diff --git a/installers/charm/lcm/requirements-test.txt b/installers/charm/lcm/requirements-test.txt
deleted file mode 100644 (file)
index cf61dd4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-mock==4.0.3
diff --git a/installers/charm/lcm/requirements.txt b/installers/charm/lcm/requirements.txt
deleted file mode 100644 (file)
index 1a8928c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master
\ No newline at end of file
diff --git a/installers/charm/lcm/src/charm.py b/installers/charm/lcm/src/charm.py
deleted file mode 100755 (executable)
index 5319763..0000000
+++ /dev/null
@@ -1,573 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213
-
-
-import logging
-from typing import NoReturn, Optional
-
-
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.main import main
-from opslib.osm.charm import CharmedOsmBase, RelationsMissing
-from opslib.osm.interfaces.http import HttpClient
-from opslib.osm.interfaces.mongo import MongoClient
-from opslib.osm.pod import ContainerV3Builder, PodRestartPolicy, PodSpecV3Builder
-from opslib.osm.validator import ModelValidator, validator
-
-
-logger = logging.getLogger(__name__)
-
-PORT = 9999
-
-
-class ConfigModel(ModelValidator):
-    vca_host: Optional[str]
-    vca_port: Optional[int]
-    vca_user: Optional[str]
-    vca_secret: Optional[str]
-    vca_pubkey: Optional[str]
-    vca_cacert: Optional[str]
-    vca_cloud: Optional[str]
-    vca_k8s_cloud: Optional[str]
-    database_commonkey: str
-    mongodb_uri: Optional[str]
-    log_level: str
-    vca_apiproxy: Optional[str]
-    # Model-config options
-    vca_model_config_agent_metadata_url: Optional[str]
-    vca_model_config_agent_stream: Optional[str]
-    vca_model_config_apt_ftp_proxy: Optional[str]
-    vca_model_config_apt_http_proxy: Optional[str]
-    vca_model_config_apt_https_proxy: Optional[str]
-    vca_model_config_apt_mirror: Optional[str]
-    vca_model_config_apt_no_proxy: Optional[str]
-    vca_model_config_automatically_retry_hooks: Optional[bool]
-    vca_model_config_backup_dir: Optional[str]
-    vca_model_config_cloudinit_userdata: Optional[str]
-    vca_model_config_container_image_metadata_url: Optional[str]
-    vca_model_config_container_image_stream: Optional[str]
-    vca_model_config_container_inherit_properties: Optional[str]
-    vca_model_config_container_networking_method: Optional[str]
-    vca_model_config_default_series: Optional[str]
-    vca_model_config_default_space: Optional[str]
-    vca_model_config_development: Optional[bool]
-    vca_model_config_disable_network_management: Optional[bool]
-    vca_model_config_egress_subnets: Optional[str]
-    vca_model_config_enable_os_refresh_update: Optional[bool]
-    vca_model_config_enable_os_upgrade: Optional[bool]
-    vca_model_config_fan_config: Optional[str]
-    vca_model_config_firewall_mode: Optional[str]
-    vca_model_config_ftp_proxy: Optional[str]
-    vca_model_config_http_proxy: Optional[str]
-    vca_model_config_https_proxy: Optional[str]
-    vca_model_config_ignore_machine_addresses: Optional[bool]
-    vca_model_config_image_metadata_url: Optional[str]
-    vca_model_config_image_stream: Optional[str]
-    vca_model_config_juju_ftp_proxy: Optional[str]
-    vca_model_config_juju_http_proxy: Optional[str]
-    vca_model_config_juju_https_proxy: Optional[str]
-    vca_model_config_juju_no_proxy: Optional[str]
-    vca_model_config_logforward_enabled: Optional[bool]
-    vca_model_config_logging_config: Optional[str]
-    vca_model_config_lxd_snap_channel: Optional[str]
-    vca_model_config_max_action_results_age: Optional[str]
-    vca_model_config_max_action_results_size: Optional[str]
-    vca_model_config_max_status_history_age: Optional[str]
-    vca_model_config_max_status_history_size: Optional[str]
-    vca_model_config_net_bond_reconfigure_delay: Optional[str]
-    vca_model_config_no_proxy: Optional[str]
-    vca_model_config_provisioner_harvest_mode: Optional[str]
-    vca_model_config_proxy_ssh: Optional[bool]
-    vca_model_config_snap_http_proxy: Optional[str]
-    vca_model_config_snap_https_proxy: Optional[str]
-    vca_model_config_snap_store_assertions: Optional[str]
-    vca_model_config_snap_store_proxy: Optional[str]
-    vca_model_config_snap_store_proxy_url: Optional[str]
-    vca_model_config_ssl_hostname_verification: Optional[bool]
-    vca_model_config_test_mode: Optional[bool]
-    vca_model_config_transmit_vendor_metrics: Optional[bool]
-    vca_model_config_update_status_hook_interval: Optional[str]
-    vca_stablerepourl: Optional[str]
-    vca_helm_ca_certs: Optional[str]
-    image_pull_policy: str
-    debug_mode: bool
-    security_context: bool
-
-    @validator("log_level")
-    def validate_log_level(cls, v):
-        if v not in {"INFO", "DEBUG"}:
-            raise ValueError("value must be INFO or DEBUG")
-        return v
-
-    @validator("mongodb_uri")
-    def validate_mongodb_uri(cls, v):
-        if v and not v.startswith("mongodb://"):
-            raise ValueError("mongodb_uri is not properly formed")
-        return v
-
-    @validator("image_pull_policy")
-    def validate_image_pull_policy(cls, v):
-        values = {
-            "always": "Always",
-            "ifnotpresent": "IfNotPresent",
-            "never": "Never",
-        }
-        v = v.lower()
-        if v not in values.keys():
-            raise ValueError("value must be always, ifnotpresent or never")
-        return values[v]
-
-
-class LcmCharm(CharmedOsmBase):
-    on = KafkaEvents()
-
-    def __init__(self, *args) -> NoReturn:
-        super().__init__(
-            *args,
-            oci_image="image",
-            vscode_workspace=VSCODE_WORKSPACE,
-        )
-        if self.config.get("debug_mode"):
-            self.enable_debug_mode(
-                pubkey=self.config.get("debug_pubkey"),
-                hostpaths={
-                    "LCM": {
-                        "hostpath": self.config.get("debug_lcm_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_lcm",
-                    },
-                    "N2VC": {
-                        "hostpath": self.config.get("debug_n2vc_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/n2vc",
-                    },
-                    "osm_common": {
-                        "hostpath": self.config.get("debug_common_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_common",
-                    },
-                },
-            )
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(self.on.kafka_available, self.configure_pod)
-        self.framework.observe(self.on.kafka_broken, self.configure_pod)
-
-        self.mongodb_client = MongoClient(self, "mongodb")
-        self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
-
-        self.ro_client = HttpClient(self, "ro")
-        self.framework.observe(self.on["ro"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["ro"].relation_broken, self.configure_pod)
-
-    def _check_missing_dependencies(self, config: ConfigModel):
-        missing_relations = []
-
-        if not self.kafka.host or not self.kafka.port:
-            missing_relations.append("kafka")
-        if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
-            missing_relations.append("mongodb")
-        if self.ro_client.is_missing_data_in_app():
-            missing_relations.append("ro")
-
-        if missing_relations:
-            raise RelationsMissing(missing_relations)
-
-    def build_pod_spec(self, image_info):
-        # Validate config
-        config = ConfigModel(**dict(self.config))
-
-        if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
-            raise Exception("Mongodb data cannot be provided via config and relation")
-
-        # Check relations
-        self._check_missing_dependencies(config)
-
-        security_context_enabled = (
-            config.security_context if not config.debug_mode else False
-        )
-
-        # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder(
-            enable_security_context=security_context_enabled
-        )
-
-        # Add secrets to the pod
-        mongodb_secret_name = f"{self.app.name}-mongodb-secret"
-        pod_spec_builder.add_secret(
-            mongodb_secret_name,
-            {
-                "uri": config.mongodb_uri or self.mongodb_client.connection_string,
-                "commonkey": config.database_commonkey,
-                "helm_ca_certs": config.vca_helm_ca_certs,
-            },
-        )
-
-        # Build Container
-        container_builder = ContainerV3Builder(
-            self.app.name,
-            image_info,
-            config.image_pull_policy,
-            run_as_non_root=security_context_enabled,
-        )
-        container_builder.add_port(name=self.app.name, port=PORT)
-        container_builder.add_envs(
-            {
-                # General configuration
-                "ALLOW_ANONYMOUS_LOGIN": "yes",
-                "OSMLCM_GLOBAL_LOGLEVEL": config.log_level,
-                # RO configuration
-                "OSMLCM_RO_HOST": self.ro_client.host,
-                "OSMLCM_RO_PORT": self.ro_client.port,
-                "OSMLCM_RO_TENANT": "osm",
-                # Kafka configuration
-                "OSMLCM_MESSAGE_DRIVER": "kafka",
-                "OSMLCM_MESSAGE_HOST": self.kafka.host,
-                "OSMLCM_MESSAGE_PORT": self.kafka.port,
-                # Database configuration
-                "OSMLCM_DATABASE_DRIVER": "mongo",
-                # Storage configuration
-                "OSMLCM_STORAGE_DRIVER": "mongo",
-                "OSMLCM_STORAGE_PATH": "/app/storage",
-                "OSMLCM_STORAGE_COLLECTION": "files",
-                "OSMLCM_VCA_STABLEREPOURL": config.vca_stablerepourl,
-            }
-        )
-        container_builder.add_secret_envs(
-            secret_name=mongodb_secret_name,
-            envs={
-                "OSMLCM_DATABASE_URI": "uri",
-                "OSMLCM_DATABASE_COMMONKEY": "commonkey",
-                "OSMLCM_STORAGE_URI": "uri",
-                "OSMLCM_VCA_HELM_CA_CERTS": "helm_ca_certs",
-            },
-        )
-        if config.vca_host:
-            vca_secret_name = f"{self.app.name}-vca-secret"
-            pod_spec_builder.add_secret(
-                vca_secret_name,
-                {
-                    "host": config.vca_host,
-                    "port": str(config.vca_port),
-                    "user": config.vca_user,
-                    "pubkey": config.vca_pubkey,
-                    "secret": config.vca_secret,
-                    "cacert": config.vca_cacert,
-                    "cloud": config.vca_cloud,
-                    "k8s_cloud": config.vca_k8s_cloud,
-                },
-            )
-            container_builder.add_secret_envs(
-                secret_name=vca_secret_name,
-                envs={
-                    # VCA configuration
-                    "OSMLCM_VCA_HOST": "host",
-                    "OSMLCM_VCA_PORT": "port",
-                    "OSMLCM_VCA_USER": "user",
-                    "OSMLCM_VCA_PUBKEY": "pubkey",
-                    "OSMLCM_VCA_SECRET": "secret",
-                    "OSMLCM_VCA_CACERT": "cacert",
-                    "OSMLCM_VCA_CLOUD": "cloud",
-                    "OSMLCM_VCA_K8S_CLOUD": "k8s_cloud",
-                },
-            )
-            if config.vca_apiproxy:
-                container_builder.add_env("OSMLCM_VCA_APIPROXY", config.vca_apiproxy)
-
-            model_config_envs = {
-                f"OSMLCM_{k.upper()}": v
-                for k, v in self.config.items()
-                if k.startswith("vca_model_config")
-            }
-            if model_config_envs:
-                container_builder.add_envs(model_config_envs)
-        container = container_builder.build()
-
-        # Add container to pod spec
-        pod_spec_builder.add_container(container)
-
-        # Add restart policy
-        restart_policy = PodRestartPolicy()
-        restart_policy.add_secrets()
-        pod_spec_builder.set_restart_policy(restart_policy)
-
-        return pod_spec_builder.build()
-
-
-VSCODE_WORKSPACE = {
-    "folders": [
-        {"path": "/usr/lib/python3/dist-packages/osm_lcm"},
-        {"path": "/usr/lib/python3/dist-packages/n2vc"},
-        {"path": "/usr/lib/python3/dist-packages/osm_common"},
-    ],
-    "settings": {},
-    "launch": {
-        "version": "0.2.0",
-        "configurations": [
-            {
-                "name": "LCM",
-                "type": "python",
-                "request": "launch",
-                "module": "osm_lcm.lcm",
-                "justMyCode": False,
-            }
-        ],
-    },
-}
-
-
-if __name__ == "__main__":
-    main(LcmCharm)
-
-
-# class ConfigurePodEvent(EventBase):
-#     """Configure Pod event"""
-
-#     pass
-
-
-# class LcmEvents(CharmEvents):
-#     """LCM Events"""
-
-#     configure_pod = EventSource(ConfigurePodEvent)
-
-
-# class LcmCharm(CharmBase):
-#     """LCM Charm."""
-
-#     state = StoredState()
-#     on = LcmEvents()
-
-#     def __init__(self, *args) -> NoReturn:
-#         """LCM Charm constructor."""
-#         super().__init__(*args)
-
-#         # Internal state initialization
-#         self.state.set_default(pod_spec=None)
-
-#         # Message bus data initialization
-#         self.state.set_default(message_host=None)
-#         self.state.set_default(message_port=None)
-
-#         # Database data initialization
-#         self.state.set_default(database_uri=None)
-
-#         # RO data initialization
-#         self.state.set_default(ro_host=None)
-#         self.state.set_default(ro_port=None)
-
-#         self.port = LCM_PORT
-#         self.image = OCIImageResource(self, "image")
-
-#         # Registering regular events
-#         self.framework.observe(self.on.start, self.configure_pod)
-#         self.framework.observe(self.on.config_changed, self.configure_pod)
-#         self.framework.observe(self.on.upgrade_charm, self.configure_pod)
-
-#         # Registering custom internal events
-#         self.framework.observe(self.on.configure_pod, self.configure_pod)
-
-#         # Registering required relation events
-#         self.framework.observe(
-#             self.on.kafka_relation_changed, self._on_kafka_relation_changed
-#         )
-#         self.framework.observe(
-#             self.on.mongodb_relation_changed, self._on_mongodb_relation_changed
-#         )
-#         self.framework.observe(
-#             self.on.ro_relation_changed, self._on_ro_relation_changed
-#         )
-
-#         # Registering required relation broken events
-#         self.framework.observe(
-#             self.on.kafka_relation_broken, self._on_kafka_relation_broken
-#         )
-#         self.framework.observe(
-#             self.on.mongodb_relation_broken, self._on_mongodb_relation_broken
-#         )
-#         self.framework.observe(
-#             self.on.ro_relation_broken, self._on_ro_relation_broken
-#         )
-
-#     def _on_kafka_relation_changed(self, event: EventBase) -> NoReturn:
-#         """Reads information about the kafka relation.
-
-#         Args:
-#             event (EventBase): Kafka relation event.
-#         """
-#         message_host = event.relation.data[event.unit].get("host")
-#         message_port = event.relation.data[event.unit].get("port")
-
-#         if (
-#             message_host
-#             and message_port
-#             and (
-#                 self.state.message_host != message_host
-#                 or self.state.message_port != message_port
-#             )
-#         ):
-#             self.state.message_host = message_host
-#             self.state.message_port = message_port
-#             self.on.configure_pod.emit()
-
-#     def _on_kafka_relation_broken(self, event: EventBase) -> NoReturn:
-#         """Clears data from kafka relation.
-
-#         Args:
-#             event (EventBase): Kafka relation event.
-#         """
-#         self.state.message_host = None
-#         self.state.message_port = None
-#         self.on.configure_pod.emit()
-
-#     def _on_mongodb_relation_changed(self, event: EventBase) -> NoReturn:
-#         """Reads information about the DB relation.
-
-#         Args:
-#             event (EventBase): DB relation event.
-#         """
-#         database_uri = event.relation.data[event.unit].get("connection_string")
-
-#         if database_uri and self.state.database_uri != database_uri:
-#             self.state.database_uri = database_uri
-#             self.on.configure_pod.emit()
-
-#     def _on_mongodb_relation_broken(self, event: EventBase) -> NoReturn:
-#         """Clears data from mongodb relation.
-
-#         Args:
-#             event (EventBase): DB relation event.
-#         """
-#         self.state.database_uri = None
-#         self.on.configure_pod.emit()
-
-#     def _on_ro_relation_changed(self, event: EventBase) -> NoReturn:
-#         """Reads information about the RO relation.
-
-#         Args:
-#             event (EventBase): Keystone relation event.
-#         """
-#         ro_host = event.relation.data[event.unit].get("host")
-#         ro_port = event.relation.data[event.unit].get("port")
-
-#         if (
-#             ro_host
-#             and ro_port
-#             and (self.state.ro_host != ro_host or self.state.ro_port != ro_port)
-#         ):
-#             self.state.ro_host = ro_host
-#             self.state.ro_port = ro_port
-#             self.on.configure_pod.emit()
-
-#     def _on_ro_relation_broken(self, event: EventBase) -> NoReturn:
-#         """Clears data from ro relation.
-
-#         Args:
-#             event (EventBase): Keystone relation event.
-#         """
-#         self.state.ro_host = None
-#         self.state.ro_port = None
-#         self.on.configure_pod.emit()
-
-#     def _missing_relations(self) -> str:
-#         """Checks if there missing relations.
-
-#         Returns:
-#             str: string with missing relations
-#         """
-#         data_status = {
-#             "kafka": self.state.message_host,
-#             "mongodb": self.state.database_uri,
-#             "ro": self.state.ro_host,
-#         }
-
-#         missing_relations = [k for k, v in data_status.items() if not v]
-
-#         return ", ".join(missing_relations)
-
-#     @property
-#     def relation_state(self) -> Dict[str, Any]:
-#         """Collects relation state configuration for pod spec assembly.
-
-#         Returns:
-#             Dict[str, Any]: relation state information.
-#         """
-#         relation_state = {
-#             "message_host": self.state.message_host,
-#             "message_port": self.state.message_port,
-#             "database_uri": self.state.database_uri,
-#             "ro_host": self.state.ro_host,
-#             "ro_port": self.state.ro_port,
-#         }
-
-#         return relation_state
-
-#     def configure_pod(self, event: EventBase) -> NoReturn:
-#         """Assemble the pod spec and apply it, if possible.
-
-#         Args:
-#             event (EventBase): Hook or Relation event that started the
-#                                function.
-#         """
-#         if missing := self._missing_relations():
-#             self.unit.status = BlockedStatus(
-#                 "Waiting for {0} relation{1}".format(
-#                     missing, "s" if "," in missing else ""
-#                 )
-#             )
-#             return
-
-#         if not self.unit.is_leader():
-#             self.unit.status = ActiveStatus("ready")
-#             return
-
-#         self.unit.status = MaintenanceStatus("Assembling pod spec")
-
-#         # Fetch image information
-#         try:
-#             self.unit.status = MaintenanceStatus("Fetching image information")
-#             image_info = self.image.fetch()
-#         except OCIImageResourceError:
-#             self.unit.status = BlockedStatus("Error fetching image information")
-#             return
-
-#         try:
-#             pod_spec = make_pod_spec(
-#                 image_info,
-#                 self.model.config,
-#                 self.relation_state,
-#                 self.model.app.name,
-#                 self.port,
-#             )
-#         except ValueError as exc:
-#             logger.exception("Config/Relation data validation error")
-#             self.unit.status = BlockedStatus(str(exc))
-#             return
-
-#         if self.state.pod_spec != pod_spec:
-#             self.model.pod.set_spec(pod_spec)
-#             self.state.pod_spec = pod_spec
-
-#         self.unit.status = ActiveStatus("ready")
-
-
-# if __name__ == "__main__":
-#     main(LcmCharm)
diff --git a/installers/charm/lcm/src/pod_spec.py b/installers/charm/lcm/src/pod_spec.py
deleted file mode 100644 (file)
index 8709f4f..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import logging
-from typing import Any, Dict, List, NoReturn
-
-logger = logging.getLogger(__name__)
-
-
-def _validate_data(
-    config_data: Dict[str, Any], relation_data: Dict[str, Any]
-) -> NoReturn:
-    """Validate input data.
-
-    Args:
-        config_data (Dict[str, Any]): configuration data.
-        relation_data (Dict[str, Any]): relation data.
-    """
-    config_validators = {
-        "database_commonkey": lambda value, _: (
-            isinstance(value, str) and len(value) > 1
-        ),
-        "log_level": lambda value, _: (
-            isinstance(value, str) and value in ("INFO", "DEBUG")
-        ),
-        "vca_host": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "vca_port": lambda value, _: isinstance(value, int) and value > 0,
-        "vca_user": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "vca_pubkey": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "vca_password": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "vca_cacert": lambda value, _: isinstance(value, str),
-        "vca_cloud": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "vca_k8s_cloud": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "vca_apiproxy": lambda value, _: (isinstance(value, str) and len(value) > 1)
-        if value
-        else True,
-    }
-    relation_validators = {
-        "ro_host": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "ro_port": lambda value, _: isinstance(value, int) and value > 0,
-        "message_host": lambda value, _: isinstance(value, str) and len(value) > 1,
-        "message_port": lambda value, _: isinstance(value, int) and value > 0,
-        "database_uri": lambda value, _: isinstance(value, str) and len(value) > 1,
-    }
-    problems = []
-
-    for key, validator in config_validators.items():
-        valid = validator(config_data.get(key), config_data)
-
-        if not valid:
-            problems.append(key)
-
-    for key, validator in relation_validators.items():
-        valid = validator(relation_data.get(key), relation_data)
-
-        if not valid:
-            problems.append(key)
-
-    if len(problems) > 0:
-        raise ValueError("Errors found in: {}".format(", ".join(problems)))
-
-
-def _make_pod_ports(port: int) -> List[Dict[str, Any]]:
-    """Generate pod ports details.
-
-    Args:
-        port (int): port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod port details.
-    """
-    return [{"name": "lcm", "containerPort": port, "protocol": "TCP"}]
-
-
-def _make_pod_envconfig(
-    config: Dict[str, Any], relation_state: Dict[str, Any]
-) -> Dict[str, Any]:
-    """Generate pod environment configuration.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-        relation_state (Dict[str, Any]): relation state information.
-
-    Returns:
-        Dict[str, Any]: pod environment configuration.
-    """
-    envconfig = {
-        # General configuration
-        "ALLOW_ANONYMOUS_LOGIN": "yes",
-        "OSMLCM_GLOBAL_LOGLEVEL": config["log_level"],
-        # RO configuration
-        "OSMLCM_RO_HOST": relation_state["ro_host"],
-        "OSMLCM_RO_PORT": relation_state["ro_port"],
-        "OSMLCM_RO_TENANT": "osm",
-        # Kafka configuration
-        "OSMLCM_MESSAGE_DRIVER": "kafka",
-        "OSMLCM_MESSAGE_HOST": relation_state["message_host"],
-        "OSMLCM_MESSAGE_PORT": relation_state["message_port"],
-        # Database configuration
-        "OSMLCM_DATABASE_DRIVER": "mongo",
-        "OSMLCM_DATABASE_URI": relation_state["database_uri"],
-        "OSMLCM_DATABASE_COMMONKEY": config["database_commonkey"],
-        # Storage configuration
-        "OSMLCM_STORAGE_DRIVER": "mongo",
-        "OSMLCM_STORAGE_PATH": "/app/storage",
-        "OSMLCM_STORAGE_COLLECTION": "files",
-        "OSMLCM_STORAGE_URI": relation_state["database_uri"],
-        # VCA configuration
-        "OSMLCM_VCA_HOST": config["vca_host"],
-        "OSMLCM_VCA_PORT": config["vca_port"],
-        "OSMLCM_VCA_USER": config["vca_user"],
-        "OSMLCM_VCA_PUBKEY": config["vca_pubkey"],
-        "OSMLCM_VCA_SECRET": config["vca_password"],
-        "OSMLCM_VCA_CACERT": config["vca_cacert"],
-        "OSMLCM_VCA_CLOUD": config["vca_cloud"],
-        "OSMLCM_VCA_K8S_CLOUD": config["vca_k8s_cloud"],
-    }
-
-    if "vca_apiproxy" in config and config["vca_apiproxy"]:
-        envconfig["OSMLCM_VCA_APIPROXY"] = config["vca_apiproxy"]
-
-    return envconfig
-
-
-def _make_startup_probe() -> Dict[str, Any]:
-    """Generate startup probe.
-
-    Returns:
-        Dict[str, Any]: startup probe.
-    """
-    return {
-        "exec": {"command": ["/usr/bin/pgrep python3"]},
-        "initialDelaySeconds": 60,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_readiness_probe(port: int) -> Dict[str, Any]:
-    """Generate readiness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: readiness probe.
-    """
-    return {
-        "httpGet": {
-            "path": "/osm/",
-            "port": port,
-        },
-        "initialDelaySeconds": 45,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_liveness_probe(port: int) -> Dict[str, Any]:
-    """Generate liveness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: liveness probe.
-    """
-    return {
-        "httpGet": {
-            "path": "/osm/",
-            "port": port,
-        },
-        "initialDelaySeconds": 45,
-        "timeoutSeconds": 5,
-    }
-
-
-def make_pod_spec(
-    image_info: Dict[str, str],
-    config: Dict[str, Any],
-    relation_state: Dict[str, Any],
-    app_name: str = "lcm",
-    port: int = 9999,
-) -> Dict[str, Any]:
-    """Generate the pod spec information.
-
-    Args:
-        image_info (Dict[str, str]): Object provided by
-                                     OCIImageResource("image").fetch().
-        config (Dict[str, Any]): Configuration information.
-        relation_state (Dict[str, Any]): Relation state information.
-        app_name (str, optional): Application name. Defaults to "lcm".
-        port (int, optional): Port for the container. Defaults to 9999.
-
-    Returns:
-        Dict[str, Any]: Pod spec dictionary for the charm.
-    """
-    if not image_info:
-        return None
-
-    _validate_data(config, relation_state)
-
-    ports = _make_pod_ports(port)
-    env_config = _make_pod_envconfig(config, relation_state)
-
-    return {
-        "version": 3,
-        "containers": [
-            {
-                "name": app_name,
-                "imageDetails": image_info,
-                "imagePullPolicy": "Always",
-                "ports": ports,
-                "envConfig": env_config,
-            }
-        ],
-        "kubernetesResources": {
-            "ingressResources": [],
-        },
-    }
diff --git a/installers/charm/lcm/tests/__init__.py b/installers/charm/lcm/tests/__init__.py
deleted file mode 100644 (file)
index 446d5ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-"""Init mocking for unit tests."""
-
-import sys
-
-
-import mock
-
-
-class OCIImageResourceErrorMock(Exception):
-    pass
-
-
-sys.path.append("src")
-
-oci_image = mock.MagicMock()
-oci_image.OCIImageResourceError = OCIImageResourceErrorMock
-sys.modules["oci_image"] = oci_image
-sys.modules["oci_image"].OCIImageResource().fetch.return_value = {}
diff --git a/installers/charm/lcm/tests/test_charm.py b/installers/charm/lcm/tests/test_charm.py
deleted file mode 100644 (file)
index aa11a74..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import sys
-from typing import NoReturn
-import unittest
-
-from charm import LcmCharm
-import mock
-from ops.model import ActiveStatus, BlockedStatus
-from ops.testing import Harness
-
-
-class TestCharm(unittest.TestCase):
-    """LCM Charm unit tests."""
-
-    def setUp(self) -> NoReturn:
-        """Test setup"""
-        self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
-        self.harness = Harness(LcmCharm)
-        self.harness.set_leader(is_leader=True)
-        self.harness.begin()
-        self.config = {
-            "vca_host": "192.168.0.13",
-            "vca_port": 17070,
-            "vca_user": "admin",
-            "vca_secret": "admin",
-            "vca_pubkey": "key",
-            "vca_cacert": "cacert",
-            "vca_cloud": "cloud",
-            "vca_k8s_cloud": "k8scloud",
-            "database_commonkey": "commonkey",
-            "mongodb_uri": "",
-            "log_level": "INFO",
-        }
-        self.harness.update_config(self.config)
-
-    def test_config_changed_no_relations(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["mongodb", "kafka", "ro"]
-            )
-        )
-
-    def test_config_changed_non_leader(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-        self.harness.set_leader(is_leader=False)
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-    def test_with_relations_and_mongodb_config(
-        self,
-    ) -> NoReturn:
-        "Test with relations and mongodb config"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_config()
-        self.initialize_ro_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations(
-        self,
-    ) -> NoReturn:
-        "Test with relations (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_ro_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_exception_mongodb_relation_and_config(
-        self,
-    ) -> NoReturn:
-        "Test with all relations and config for mongodb. Must fail"
-        self.initialize_mongo_relation()
-        self.initialize_mongo_config()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    # def test_build_pod_spec(
-    #     self,
-    # ) -> NoReturn:
-    #     expected_config = {
-    #         "OSMLCM_GLOBAL_LOGLEVEL": self.config["log_level"],
-    #         "OSMLCM_DATABASE_COMMONKEY": self.config["database_commonkey"],
-    #     }
-    #     expected_config.update(
-    #         {
-    #             f"OSMLCM_{k.upper()}": v
-    #             for k, v in self.config.items()
-    #             if k.startswith("vca_")
-    #         }
-    #     )
-    #     self.harness.charm._check_missing_dependencies = mock.Mock()
-    #     pod_spec = self.harness.charm.build_pod_spec(
-    #         {"imageDetails": {"imagePath": "lcm-image"}}
-    #     )
-    #     actual_config = pod_spec["containers"][0]["envConfig"]
-
-    #     self.assertDictContainsSubset(
-    #         expected_config,
-    #         actual_config,
-    #     )
-    #     for config_key in actual_config:
-    #         self.assertNotIn("VCA_MODEL_CONFIG", config_key)
-
-    def test_build_pod_spec_with_model_config(
-        self,
-    ) -> NoReturn:
-        self.harness.update_config(
-            {
-                "vca_model_config_agent_metadata_url": "string",
-                "vca_model_config_agent_stream": "string",
-                "vca_model_config_apt_ftp_proxy": "string",
-                "vca_model_config_apt_http_proxy": "string",
-                "vca_model_config_apt_https_proxy": "string",
-                "vca_model_config_apt_mirror": "string",
-                "vca_model_config_apt_no_proxy": "string",
-                "vca_model_config_automatically_retry_hooks": False,
-                "vca_model_config_backup_dir": "string",
-                "vca_model_config_cloudinit_userdata": "string",
-                "vca_model_config_container_image_metadata_url": "string",
-                "vca_model_config_container_image_stream": "string",
-                "vca_model_config_container_inherit_properties": "string",
-                "vca_model_config_container_networking_method": "string",
-                "vca_model_config_default_series": "string",
-                "vca_model_config_default_space": "string",
-                "vca_model_config_development": False,
-                "vca_model_config_disable_network_management": False,
-                "vca_model_config_egress_subnets": "string",
-                "vca_model_config_enable_os_refresh_update": False,
-                "vca_model_config_enable_os_upgrade": False,
-                "vca_model_config_fan_config": "string",
-                "vca_model_config_firewall_mode": "string",
-                "vca_model_config_ftp_proxy": "string",
-                "vca_model_config_http_proxy": "string",
-                "vca_model_config_https_proxy": "string",
-                "vca_model_config_ignore_machine_addresses": False,
-                "vca_model_config_image_metadata_url": "string",
-                "vca_model_config_image_stream": "string",
-                "vca_model_config_juju_ftp_proxy": "string",
-                "vca_model_config_juju_http_proxy": "string",
-                "vca_model_config_juju_https_proxy": "string",
-                "vca_model_config_juju_no_proxy": "string",
-                "vca_model_config_logforward_enabled": False,
-                "vca_model_config_logging_config": "string",
-                "vca_model_config_lxd_snap_channel": "string",
-                "vca_model_config_max_action_results_age": "string",
-                "vca_model_config_max_action_results_size": "string",
-                "vca_model_config_max_status_history_age": "string",
-                "vca_model_config_max_status_history_size": "string",
-                "vca_model_config_net_bond_reconfigure_delay": "string",
-                "vca_model_config_no_proxy": "string",
-                "vca_model_config_provisioner_harvest_mode": "string",
-                "vca_model_config_proxy_ssh": False,
-                "vca_model_config_snap_http_proxy": "string",
-                "vca_model_config_snap_https_proxy": "string",
-                "vca_model_config_snap_store_assertions": "string",
-                "vca_model_config_snap_store_proxy": "string",
-                "vca_model_config_snap_store_proxy_url": "string",
-                "vca_model_config_ssl_hostname_verification": False,
-                "vca_model_config_test_mode": False,
-                "vca_model_config_transmit_vendor_metrics": False,
-                "vca_model_config_update_status_hook_interval": "string",
-            }
-        )
-        expected_config = {
-            f"OSMLCM_{k.upper()}": v
-            for k, v in self.config.items()
-            if k.startswith("vca_model_config_")
-        }
-
-        self.harness.charm._check_missing_dependencies = mock.Mock()
-        pod_spec = self.harness.charm.build_pod_spec(
-            {"imageDetails": {"imagePath": "lcm-image"}}
-        )
-        actual_config = pod_spec["containers"][0]["envConfig"]
-
-        self.assertDictContainsSubset(
-            expected_config,
-            actual_config,
-        )
-
-    def initialize_kafka_relation(self):
-        kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-        self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-        self.harness.update_relation_data(
-            kafka_relation_id, "kafka", {"host": "kafka", "port": 9092}
-        )
-
-    def initialize_mongo_config(self):
-        self.harness.update_config({"mongodb_uri": "mongodb://mongo:27017"})
-
-    def initialize_mongo_relation(self):
-        mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-        self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mongodb/0",
-            {"connection_string": "mongodb://mongo:27017"},
-        )
-
-    def initialize_ro_relation(self):
-        http_relation_id = self.harness.add_relation("ro", "ro")
-        self.harness.add_relation_unit(http_relation_id, "ro")
-        self.harness.update_relation_data(
-            http_relation_id,
-            "ro",
-            {"host": "ro", "port": 9090},
-        )
-
-
-if __name__ == "__main__":
-    unittest.main()
-
-
-# class TestCharm(unittest.TestCase):
-#     """LCM Charm unit tests."""
-
-#     def setUp(self) -> NoReturn:
-#         """Test setup"""
-#         self.harness = Harness(LcmCharm)
-#         self.harness.set_leader(is_leader=True)
-#         self.harness.begin()
-
-#     def test_on_start_without_relations(self) -> NoReturn:
-#         """Test installation without any relation."""
-#         self.harness.charm.on.start.emit()
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertIn("ro", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_start_with_relations(self) -> NoReturn:
-#         """Test deployment without keystone."""
-#         expected_result = {
-#             "version": 3,
-#             "containers": [
-#                 {
-#                     "name": "lcm",
-#                     "imageDetails": self.harness.charm.image.fetch(),
-#                     "imagePullPolicy": "Always",
-#                     "ports": [
-#                         {
-#                             "name": "lcm",
-#                             "containerPort": 9999,
-#                             "protocol": "TCP",
-#                         }
-#                     ],
-#                     "envConfig": {
-#                         "ALLOW_ANONYMOUS_LOGIN": "yes",
-#                         "OSMLCM_GLOBAL_LOGLEVEL": "INFO",
-#                         "OSMLCM_RO_HOST": "ro",
-#                         "OSMLCM_RO_PORT": 9090,
-#                         "OSMLCM_RO_TENANT": "osm",
-#                         "OSMLCM_MESSAGE_DRIVER": "kafka",
-#                         "OSMLCM_MESSAGE_HOST": "kafka",
-#                         "OSMLCM_MESSAGE_PORT": 9092,
-#                         "OSMLCM_DATABASE_DRIVER": "mongo",
-#                         "OSMLCM_DATABASE_URI": "mongodb://mongo:27017",
-#                         "OSMLCM_DATABASE_COMMONKEY": "osm",
-#                         "OSMLCM_STORAGE_DRIVER": "mongo",
-#                         "OSMLCM_STORAGE_PATH": "/app/storage",
-#                         "OSMLCM_STORAGE_COLLECTION": "files",
-#                         "OSMLCM_STORAGE_URI": "mongodb://mongo:27017",
-#                         "OSMLCM_VCA_HOST": "admin",
-#                         "OSMLCM_VCA_PORT": 17070,
-#                         "OSMLCM_VCA_USER": "admin",
-#                         "OSMLCM_VCA_PUBKEY": "secret",
-#                         "OSMLCM_VCA_SECRET": "secret",
-#                         "OSMLCM_VCA_CACERT": "",
-#                         "OSMLCM_VCA_CLOUD": "localhost",
-#                         "OSMLCM_VCA_K8S_CLOUD": "k8scloud",
-#                     },
-#                 }
-#             ],
-#             "kubernetesResources": {"ingressResources": []},
-#         }
-
-#         self.harness.charm.on.start.emit()
-
-#         # Check if kafka datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.message_host)
-#         self.assertIsNone(self.harness.charm.state.message_port)
-
-#         # Check if mongodb datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.database_uri)
-
-#         # Check if RO datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.ro_host)
-#         self.assertIsNone(self.harness.charm.state.ro_port)
-
-#         # Initializing the kafka relation
-#         kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             kafka_relation_id, "kafka/0", {"host": "kafka", "port": 9092}
-#         )
-
-#         # Initializing the mongo relation
-#         mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             mongodb_relation_id,
-#             "mongodb/0",
-#             {"connection_string": "mongodb://mongo:27017"},
-#         )
-
-#         # Initializing the RO relation
-#         ro_relation_id = self.harness.add_relation("ro", "ro")
-#         self.harness.add_relation_unit(ro_relation_id, "ro/0")
-#         self.harness.update_relation_data(
-#             ro_relation_id, "ro/0", {"host": "ro", "port": 9090}
-#         )
-
-#         # Checking if kafka data is stored
-#         self.assertEqual(self.harness.charm.state.message_host, "kafka")
-#         self.assertEqual(self.harness.charm.state.message_port, 9092)
-
-#         # Checking if mongodb data is stored
-#         self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
-
-#         # Checking if RO data is stored
-#         self.assertEqual(self.harness.charm.state.ro_host, "ro")
-#         self.assertEqual(self.harness.charm.state.ro_port, 9090)
-
-#         # Verifying status
-#         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         pod_spec, _ = self.harness.get_pod_spec()
-
-#         self.assertDictEqual(expected_result, pod_spec)
-
-#     def test_on_kafka_relation_unit_changed(self) -> NoReturn:
-#         """Test to see if kafka relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.message_host)
-#         self.assertIsNone(self.harness.charm.state.message_port)
-
-#         relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             relation_id, "kafka/0", {"host": "kafka", "port": 9092}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.message_host, "kafka")
-#         self.assertEqual(self.harness.charm.state.message_port, 9092)
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertNotIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertIn("ro", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_mongodb_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if mongodb relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.database_uri)
-
-#         relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             relation_id, "mongodb/0", {"connection_string": "mongodb://mongo:27017"}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertNotIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertIn("ro", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_ro_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if RO relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.ro_host)
-#         self.assertIsNone(self.harness.charm.state.ro_port)
-
-#         relation_id = self.harness.add_relation("ro", "ro")
-#         self.harness.add_relation_unit(relation_id, "ro/0")
-#         self.harness.update_relation_data(
-#             relation_id, "ro/0", {"host": "ro", "port": 9090}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.ro_host, "ro")
-#         self.assertEqual(self.harness.charm.state.ro_port, 9090)
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertNotIn("ro", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-
-# if __name__ == "__main__":
-#     unittest.main()
diff --git a/installers/charm/lcm/tests/test_pod_spec.py b/installers/charm/lcm/tests/test_pod_spec.py
deleted file mode 100644 (file)
index c74fb10..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-from typing import NoReturn
-import unittest
-
-import pod_spec
-
-
-class TestPodSpec(unittest.TestCase):
-    """Pod spec unit tests."""
-
-    def test_make_pod_ports(self) -> NoReturn:
-        """Testing make pod ports."""
-        port = 9999
-
-        expected_result = [
-            {
-                "name": "lcm",
-                "containerPort": port,
-                "protocol": "TCP",
-            }
-        ]
-
-        pod_ports = pod_spec._make_pod_ports(9999)
-
-        self.assertListEqual(expected_result, pod_ports)
-
-    def test_make_pod_envconfig_without_vca_apiproxy(self) -> NoReturn:
-        """Teting make pod envconfig without vca_apiproxy configuration."""
-        config = {
-            "database_commonkey": "commonkey",
-            "log_level": "INFO",
-            "vca_host": "vca",
-            "vca_port": 1212,
-            "vca_user": "vca_user",
-            "vca_pubkey": "vca_pubkey",
-            "vca_password": "vca_password",
-            "vca_cacert": "vca_cacert",
-            "vca_cloud": "vca_cloud",
-            "vca_k8s_cloud": "vca_k8s_cloud",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 2181,
-            "database_uri": "mongodb://mongo",
-            "ro_host": "ro",
-            "ro_port": 9090,
-        }
-
-        expected_result = {
-            "ALLOW_ANONYMOUS_LOGIN": "yes",
-            "OSMLCM_GLOBAL_LOGLEVEL": config["log_level"],
-            "OSMLCM_RO_HOST": relation_state["ro_host"],
-            "OSMLCM_RO_PORT": relation_state["ro_port"],
-            "OSMLCM_RO_TENANT": "osm",
-            "OSMLCM_MESSAGE_DRIVER": "kafka",
-            "OSMLCM_MESSAGE_HOST": relation_state["message_host"],
-            "OSMLCM_MESSAGE_PORT": relation_state["message_port"],
-            "OSMLCM_DATABASE_DRIVER": "mongo",
-            "OSMLCM_DATABASE_URI": relation_state["database_uri"],
-            "OSMLCM_DATABASE_COMMONKEY": config["database_commonkey"],
-            "OSMLCM_STORAGE_DRIVER": "mongo",
-            "OSMLCM_STORAGE_PATH": "/app/storage",
-            "OSMLCM_STORAGE_COLLECTION": "files",
-            "OSMLCM_STORAGE_URI": relation_state["database_uri"],
-            "OSMLCM_VCA_HOST": config["vca_host"],
-            "OSMLCM_VCA_PORT": config["vca_port"],
-            "OSMLCM_VCA_USER": config["vca_user"],
-            "OSMLCM_VCA_PUBKEY": config["vca_pubkey"],
-            "OSMLCM_VCA_SECRET": config["vca_password"],
-            "OSMLCM_VCA_CACERT": config["vca_cacert"],
-            "OSMLCM_VCA_CLOUD": config["vca_cloud"],
-            "OSMLCM_VCA_K8S_CLOUD": config["vca_k8s_cloud"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_pod_envconfig_with_vca_apiproxy(self) -> NoReturn:
-        """Teting make pod envconfig with vca_apiproxy configuration."""
-        config = {
-            "database_commonkey": "commonkey",
-            "log_level": "INFO",
-            "vca_host": "vca",
-            "vca_port": 1212,
-            "vca_user": "vca_user",
-            "vca_pubkey": "vca_pubkey",
-            "vca_password": "vca_password",
-            "vca_cacert": "vca_cacert",
-            "vca_cloud": "vca_cloud",
-            "vca_k8s_cloud": "vca_k8s_cloud",
-            "vca_apiproxy": "vca_apiproxy",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 2181,
-            "database_uri": "mongodb://mongo",
-            "ro_host": "ro",
-            "ro_port": 9090,
-        }
-
-        expected_result = {
-            "ALLOW_ANONYMOUS_LOGIN": "yes",
-            "OSMLCM_GLOBAL_LOGLEVEL": config["log_level"],
-            "OSMLCM_RO_HOST": relation_state["ro_host"],
-            "OSMLCM_RO_PORT": relation_state["ro_port"],
-            "OSMLCM_RO_TENANT": "osm",
-            "OSMLCM_MESSAGE_DRIVER": "kafka",
-            "OSMLCM_MESSAGE_HOST": relation_state["message_host"],
-            "OSMLCM_MESSAGE_PORT": relation_state["message_port"],
-            "OSMLCM_DATABASE_DRIVER": "mongo",
-            "OSMLCM_DATABASE_URI": relation_state["database_uri"],
-            "OSMLCM_DATABASE_COMMONKEY": config["database_commonkey"],
-            "OSMLCM_STORAGE_DRIVER": "mongo",
-            "OSMLCM_STORAGE_PATH": "/app/storage",
-            "OSMLCM_STORAGE_COLLECTION": "files",
-            "OSMLCM_STORAGE_URI": relation_state["database_uri"],
-            "OSMLCM_VCA_HOST": config["vca_host"],
-            "OSMLCM_VCA_PORT": config["vca_port"],
-            "OSMLCM_VCA_USER": config["vca_user"],
-            "OSMLCM_VCA_PUBKEY": config["vca_pubkey"],
-            "OSMLCM_VCA_SECRET": config["vca_password"],
-            "OSMLCM_VCA_CACERT": config["vca_cacert"],
-            "OSMLCM_VCA_CLOUD": config["vca_cloud"],
-            "OSMLCM_VCA_K8S_CLOUD": config["vca_k8s_cloud"],
-            "OSMLCM_VCA_APIPROXY": config["vca_apiproxy"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_startup_probe(self) -> NoReturn:
-        """Testing make startup probe."""
-        expected_result = {
-            "exec": {"command": ["/usr/bin/pgrep python3"]},
-            "initialDelaySeconds": 60,
-            "timeoutSeconds": 5,
-        }
-
-        startup_probe = pod_spec._make_startup_probe()
-
-        self.assertDictEqual(expected_result, startup_probe)
-
-    def test_make_readiness_probe(self) -> NoReturn:
-        """Testing make readiness probe."""
-        port = 9999
-
-        expected_result = {
-            "httpGet": {
-                "path": "/osm/",
-                "port": port,
-            },
-            "initialDelaySeconds": 45,
-            "timeoutSeconds": 5,
-        }
-
-        readiness_probe = pod_spec._make_readiness_probe(port)
-
-        self.assertDictEqual(expected_result, readiness_probe)
-
-    def test_make_liveness_probe(self) -> NoReturn:
-        """Testing make liveness probe."""
-        port = 9999
-
-        expected_result = {
-            "httpGet": {
-                "path": "/osm/",
-                "port": port,
-            },
-            "initialDelaySeconds": 45,
-            "timeoutSeconds": 5,
-        }
-
-        liveness_probe = pod_spec._make_liveness_probe(port)
-
-        self.assertDictEqual(expected_result, liveness_probe)
-
-    def test_make_pod_spec(self) -> NoReturn:
-        """Testing make pod spec."""
-        image_info = {"upstream-source": "opensourcemano/lcm:8"}
-        config = {
-            "database_commonkey": "commonkey",
-            "log_level": "INFO",
-            "vca_host": "vca",
-            "vca_port": 1212,
-            "vca_user": "vca_user",
-            "vca_pubkey": "vca_pubkey",
-            "vca_password": "vca_password",
-            "vca_cacert": "vca_cacert",
-            "vca_cloud": "vca_cloud",
-            "vca_k8s_cloud": "vca_k8s_cloud",
-            "vca_apiproxy": "vca_apiproxy",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 2181,
-            "database_uri": "mongodb://mongo",
-            "ro_host": "ro",
-            "ro_port": 9090,
-        }
-        app_name = "lcm"
-        port = 9999
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": app_name,
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "ALLOW_ANONYMOUS_LOGIN": "yes",
-                        "OSMLCM_GLOBAL_LOGLEVEL": config["log_level"],
-                        "OSMLCM_RO_HOST": relation_state["ro_host"],
-                        "OSMLCM_RO_PORT": relation_state["ro_port"],
-                        "OSMLCM_RO_TENANT": "osm",
-                        "OSMLCM_MESSAGE_DRIVER": "kafka",
-                        "OSMLCM_MESSAGE_HOST": relation_state["message_host"],
-                        "OSMLCM_MESSAGE_PORT": relation_state["message_port"],
-                        "OSMLCM_DATABASE_DRIVER": "mongo",
-                        "OSMLCM_DATABASE_URI": relation_state["database_uri"],
-                        "OSMLCM_DATABASE_COMMONKEY": config["database_commonkey"],
-                        "OSMLCM_STORAGE_DRIVER": "mongo",
-                        "OSMLCM_STORAGE_PATH": "/app/storage",
-                        "OSMLCM_STORAGE_COLLECTION": "files",
-                        "OSMLCM_STORAGE_URI": relation_state["database_uri"],
-                        "OSMLCM_VCA_HOST": config["vca_host"],
-                        "OSMLCM_VCA_PORT": config["vca_port"],
-                        "OSMLCM_VCA_USER": config["vca_user"],
-                        "OSMLCM_VCA_PUBKEY": config["vca_pubkey"],
-                        "OSMLCM_VCA_SECRET": config["vca_password"],
-                        "OSMLCM_VCA_CACERT": config["vca_cacert"],
-                        "OSMLCM_VCA_CLOUD": config["vca_cloud"],
-                        "OSMLCM_VCA_K8S_CLOUD": config["vca_k8s_cloud"],
-                        "OSMLCM_VCA_APIPROXY": config["vca_apiproxy"],
-                    },
-                }
-            ],
-            "kubernetesResources": {"ingressResources": []},
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-    def test_make_pod_spec_with_vca_apiproxy(self) -> NoReturn:
-        """Testing make pod spec with vca_apiproxy."""
-        image_info = {"upstream-source": "opensourcemano/lcm:8"}
-        config = {
-            "database_commonkey": "commonkey",
-            "log_level": "INFO",
-            "vca_host": "vca",
-            "vca_port": 1212,
-            "vca_user": "vca_user",
-            "vca_pubkey": "vca_pubkey",
-            "vca_password": "vca_password",
-            "vca_cacert": "vca_cacert",
-            "vca_cloud": "vca_cloud",
-            "vca_k8s_cloud": "vca_k8s_cloud",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 2181,
-            "database_uri": "mongodb://mongo",
-            "ro_host": "ro",
-            "ro_port": 9090,
-        }
-        app_name = "lcm"
-        port = 9999
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": app_name,
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "ALLOW_ANONYMOUS_LOGIN": "yes",
-                        "OSMLCM_GLOBAL_LOGLEVEL": config["log_level"],
-                        "OSMLCM_RO_HOST": relation_state["ro_host"],
-                        "OSMLCM_RO_PORT": relation_state["ro_port"],
-                        "OSMLCM_RO_TENANT": "osm",
-                        "OSMLCM_MESSAGE_DRIVER": "kafka",
-                        "OSMLCM_MESSAGE_HOST": relation_state["message_host"],
-                        "OSMLCM_MESSAGE_PORT": relation_state["message_port"],
-                        "OSMLCM_DATABASE_DRIVER": "mongo",
-                        "OSMLCM_DATABASE_URI": relation_state["database_uri"],
-                        "OSMLCM_DATABASE_COMMONKEY": config["database_commonkey"],
-                        "OSMLCM_STORAGE_DRIVER": "mongo",
-                        "OSMLCM_STORAGE_PATH": "/app/storage",
-                        "OSMLCM_STORAGE_COLLECTION": "files",
-                        "OSMLCM_STORAGE_URI": relation_state["database_uri"],
-                        "OSMLCM_VCA_HOST": config["vca_host"],
-                        "OSMLCM_VCA_PORT": config["vca_port"],
-                        "OSMLCM_VCA_USER": config["vca_user"],
-                        "OSMLCM_VCA_PUBKEY": config["vca_pubkey"],
-                        "OSMLCM_VCA_SECRET": config["vca_password"],
-                        "OSMLCM_VCA_CACERT": config["vca_cacert"],
-                        "OSMLCM_VCA_CLOUD": config["vca_cloud"],
-                        "OSMLCM_VCA_K8S_CLOUD": config["vca_k8s_cloud"],
-                    },
-                }
-            ],
-            "kubernetesResources": {"ingressResources": []},
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-    def test_make_pod_spec_without_image_info(self) -> NoReturn:
-        """Testing make pod spec without image_info."""
-        image_info = None
-        config = {
-            "database_commonkey": "commonkey",
-            "log_level": "INFO",
-            "vca_host": "vca",
-            "vca_port": 1212,
-            "vca_user": "vca_user",
-            "vca_pubkey": "vca_pubkey",
-            "vca_password": "vca_password",
-            "vca_cacert": "vca_cacert",
-            "vca_cloud": "vca_cloud",
-            "vca_k8s_cloud": "vca_k8s_cloud",
-            "vca_apiproxy": "vca_apiproxy",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 2181,
-            "database_uri": "mongodb://mongo",
-            "ro_host": "ro",
-            "ro_port": 9090,
-        }
-        app_name = "lcm"
-        port = 9999
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertIsNone(spec)
-
-    def test_make_pod_spec_without_config(self) -> NoReturn:
-        """Testing make pod spec without config."""
-        image_info = {"upstream-source": "opensourcemano/lcm:8"}
-        config = {}
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 2181,
-            "database_uri": "mongodb://mongo",
-            "ro_host": "ro",
-            "ro_port": 9090,
-        }
-        app_name = "lcm"
-        port = 9999
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-    def test_make_pod_spec_without_relation_state(self) -> NoReturn:
-        """Testing make pod spec without relation_state."""
-        image_info = {"upstream-source": "opensourcemano/lcm:8"}
-        config = {
-            "database_commonkey": "commonkey",
-            "log_level": "INFO",
-            "vca_host": "vca",
-            "vca_port": 1212,
-            "vca_user": "vca_user",
-            "vca_pubkey": "vca_pubkey",
-            "vca_password": "vca_password",
-            "vca_cacert": "vca_cacert",
-            "vca_cloud": "vca_cloud",
-            "vca_k8s_cloud": "vca_k8s_cloud",
-            "vca_apiproxy": "vca_apiproxy",
-        }
-        relation_state = {}
-        app_name = "lcm"
-        port = 9999
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/lcm/tox.ini b/installers/charm/lcm/tox.ini
deleted file mode 100644 (file)
index f3c9144..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-#######################################################################################
-
-[tox]
-envlist = black, cover, flake8, pylint, yamllint, safety
-skipsdist = true
-
-[tox:jenkins]
-toxworkdir = /tmp/.tox
-
-[testenv]
-basepython = python3.8
-setenv =
-  VIRTUAL_ENV={envdir}
-  PYTHONPATH = {toxinidir}:{toxinidir}/lib:{toxinidir}/src
-  PYTHONDONTWRITEBYTECODE = 1
-deps =  -r{toxinidir}/requirements.txt
-
-
-#######################################################################################
-[testenv:black]
-deps = black
-commands =
-        black --check --diff src/ tests/
-
-
-#######################################################################################
-[testenv:cover]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        coverage
-        nose2
-commands =
-        sh -c 'rm -f nosetests.xml'
-        coverage erase
-        nose2 -C --coverage src
-        coverage report --omit='*tests*'
-        coverage html -d ./cover --omit='*tests*'
-        coverage xml -o coverage.xml --omit=*tests*
-whitelist_externals = sh
-
-
-#######################################################################################
-[testenv:flake8]
-deps =  flake8
-        flake8-import-order
-commands =
-        flake8 src/ tests/
-
-
-#######################################################################################
-[testenv:pylint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        pylint==2.10.2
-commands =
-    pylint -E src/ tests/
-
-
-#######################################################################################
-[testenv:safety]
-setenv =
-        LC_ALL=C.UTF-8
-        LANG=C.UTF-8
-deps =  {[testenv]deps}
-        safety
-commands =
-        - safety check --full-report
-
-
-#######################################################################################
-[testenv:yamllint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        yamllint
-commands = yamllint .
-
-#######################################################################################
-[testenv:build]
-passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
-whitelist_externals =
-  charmcraft
-  sh
-commands =
-  charmcraft pack
-  sh -c 'ubuntu_version=20.04; \
-        architectures="amd64-aarch64-arm64"; \
-        charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \
-        mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm'
-
-#######################################################################################
-[flake8]
-ignore =
-        W291,
-        W293,
-        W503,
-        E123,
-        E125,
-        E226,
-        E241,
-exclude =
-        .git,
-        __pycache__,
-        .tox,
-max-line-length = 120
-show-source = True
-builtins = _
-max-complexity = 10
-import-order-style = google
diff --git a/installers/charm/lint.sh b/installers/charm/lint.sh
deleted file mode 100755 (executable)
index 3c42dd1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-
-set -eux
-
-function lint() {
-    cd $1
-    tox -e lint
-    cd ..
-}
-
-lint 'lcm-k8s'
-lint 'mon-k8s'
-lint 'nbi-k8s'
-lint 'pol-k8s'
-lint 'ro-k8s'
-lint 'ui-k8s'
-lint 'keystone'
-lint 'ng-ui'
-lint 'pla'
\ No newline at end of file
diff --git a/installers/charm/mon/.gitignore b/installers/charm/mon/.gitignore
deleted file mode 100644 (file)
index 2885df2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.stestr
-cover
-release
\ No newline at end of file
diff --git a/installers/charm/mon/.jujuignore b/installers/charm/mon/.jujuignore
deleted file mode 100644 (file)
index 3ae3e7d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.gitignore
-.stestr
-cover
-release
-tests/
-requirements*
-tox.ini
diff --git a/installers/charm/mon/.yamllint.yaml b/installers/charm/mon/.yamllint.yaml
deleted file mode 100644 (file)
index d71fb69..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
----
-extends: default
-
-yaml-files:
-  - "*.yaml"
-  - "*.yml"
-  - ".yamllint"
-ignore: |
-  .tox
-  cover/
-  build/
-  venv
-  release/
diff --git a/installers/charm/mon/README.md b/installers/charm/mon/README.md
deleted file mode 100644 (file)
index 216a784..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<!-- Copyright 2020 Canonical Ltd.
-
-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.
-
-For those usages not covered by the Apache License, Version 2.0 please
-contact: legal@canonical.com
-
-To get in touch with the maintainers, please contact:
-osm-charmers@lists.launchpad.net -->
-
-# MON operator Charm for Kubernetes
-
-## Requirements
diff --git a/installers/charm/mon/charmcraft.yaml b/installers/charm/mon/charmcraft.yaml
deleted file mode 100644 (file)
index 0a285a9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-type: charm
-bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: ["amd64"]
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-          - aarch64
-          - arm64
-parts:
-  charm:
-    build-packages: [git]
diff --git a/installers/charm/mon/config.yaml b/installers/charm/mon/config.yaml
deleted file mode 100644 (file)
index 04f52c0..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-options:
-  openstack_default_granularity:
-    description: Openstack default granularity
-    type: int
-    default: 300
-  global_request_timeout:
-    description: Global request timeout
-    type: int
-    default: 10
-  log_level:
-    description: Log level
-    type: string
-    default: INFO
-  database_commonkey:
-    description: Database common key
-    type: string
-    default: osm
-  mongodb_uri:
-    type: string
-    description: MongoDB URI (external database)
-  collector_interval:
-    description: Collector interval
-    type: int
-    default: 30
-  evaluator_interval:
-    description: Evaluator interval
-    type: int
-    default: 30
-  vca_host:
-    type: string
-    description: "The VCA host."
-    default: "admin"
-  vca_user:
-    type: string
-    description: "The VCA user name."
-    default: "admin"
-  vca_secret:
-    type: string
-    description: "The VCA user password."
-    default: "secret"
-  vca_cacert:
-    type: string
-    description: "The VCA cacert."
-    default: ""
-  grafana_url:
-    description: Grafana URL
-    type: string
-    default: http://grafana:3000
-  grafana_user:
-    description: Grafana user
-    type: string
-    default: admin
-  grafana_password:
-    description: Grafana password
-    type: string
-    default: admin
-  keystone_enabled:
-    description: MON will use Keystone backend
-    type: boolean
-    default: false
-  certificates:
-    type: string
-    description: |
-      comma-separated list of <name>:<content> certificates.
-      Where:
-        name: name of the file for the certificate
-        content: base64 content of the certificate
-      The path for the files is /certs.
-  image_pull_policy:
-    type: string
-    description: |
-      ImagePullPolicy configuration for the pod.
-      Possible values: always, ifnotpresent, never
-    default: always
-  debug_mode:
-    description: |
-      If true, debug mode is activated. It means that the service will not run,
-      and instead, the command for the container will be a `sleep infinity`.
-      Note: If enabled, security_context will be disabled.
-    type: boolean
-    default: false
-  debug_pubkey:
-    description: |
-      Public SSH key that will be injected to the application pod.
-    type: string
-  debug_mon_local_path:
-    description: |
-      Local full path to the MON project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  debug_n2vc_local_path:
-    description: |
-      Local full path to the N2VC project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  debug_common_local_path:
-    description: |
-      Local full path to the COMMON project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  security_context:
-    description: Enables the security context of the pods
-    type: boolean
-    default: false
-  vm_infra_metrics:
-    description: Enables querying the VIMs asking for the status of the VMs
-    type: boolean
-    default: true
diff --git a/installers/charm/mon/lib/charms/kafka_k8s/v0/kafka.py b/installers/charm/mon/lib/charms/kafka_k8s/v0/kafka.py
deleted file mode 100644 (file)
index 1baf9a8..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2022 Canonical Ltd.
-# See LICENSE file for licensing details.
-#
-# 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.
-
-"""Kafka library.
-
-This [library](https://juju.is/docs/sdk/libraries) implements both sides of the
-`kafka` [interface](https://juju.is/docs/sdk/relations).
-
-The *provider* side of this interface is implemented by the
-[kafka-k8s Charmed Operator](https://charmhub.io/kafka-k8s).
-
-Any Charmed Operator that *requires* Kafka for providing its
-service should implement the *requirer* side of this interface.
-
-In a nutshell using this library to implement a Charmed Operator *requiring*
-Kafka would look like
-
-```
-$ charmcraft fetch-lib charms.kafka_k8s.v0.kafka
-```
-
-`metadata.yaml`:
-
-```
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-```
-
-`src/charm.py`:
-
-```
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.charm import CharmBase
-
-
-class MyCharm(CharmBase):
-
-    on = KafkaEvents()
-
-    def __init__(self, *args):
-        super().__init__(*args)
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(
-            self.on.kafka_available,
-            self._on_kafka_available,
-        )
-        self.framework.observe(
-            self.on.kafka_broken,
-            self._on_kafka_broken,
-        )
-
-    def _on_kafka_available(self, event):
-        # Get Kafka host and port
-        host: str = self.kafka.host
-        port: int = self.kafka.port
-        # host => "kafka-k8s"
-        # port => 9092
-
-    def _on_kafka_broken(self, event):
-        # Stop service
-        # ...
-        self.unit.status = BlockedStatus("need kafka relation")
-```
-
-You can file bugs
-[here](https://github.com/charmed-osm/kafka-k8s-operator/issues)!
-"""
-
-from typing import Optional
-
-from ops.charm import CharmBase, CharmEvents
-from ops.framework import EventBase, EventSource, Object
-
-# The unique Charmhub library identifier, never change it
-from ops.model import Relation
-
-LIBID = "eacc8c85082347c9aae740e0220b8376"
-
-# Increment this major API version when introducing breaking changes
-LIBAPI = 0
-
-# Increment this PATCH version before using `charmcraft publish-lib` or reset
-# to 0 if you are raising the major API version
-LIBPATCH = 3
-
-
-KAFKA_HOST_APP_KEY = "host"
-KAFKA_PORT_APP_KEY = "port"
-
-
-class _KafkaAvailableEvent(EventBase):
-    """Event emitted when Kafka is available."""
-
-
-class _KafkaBrokenEvent(EventBase):
-    """Event emitted when Kafka relation is broken."""
-
-
-class KafkaEvents(CharmEvents):
-    """Kafka events.
-
-    This class defines the events that Kafka can emit.
-
-    Events:
-        kafka_available (_KafkaAvailableEvent)
-    """
-
-    kafka_available = EventSource(_KafkaAvailableEvent)
-    kafka_broken = EventSource(_KafkaBrokenEvent)
-
-
-class KafkaRequires(Object):
-    """Requires-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self.charm = charm
-        self._endpoint_name = endpoint_name
-
-        # Observe relation events
-        event_observe_mapping = {
-            charm.on[self._endpoint_name].relation_changed: self._on_relation_changed,
-            charm.on[self._endpoint_name].relation_broken: self._on_relation_broken,
-        }
-        for event, observer in event_observe_mapping.items():
-            self.framework.observe(event, observer)
-
-    def _on_relation_changed(self, event) -> None:
-        if event.relation.app and all(
-            key in event.relation.data[event.relation.app]
-            for key in (KAFKA_HOST_APP_KEY, KAFKA_PORT_APP_KEY)
-        ):
-            self.charm.on.kafka_available.emit()
-
-    def _on_relation_broken(self, _) -> None:
-        self.charm.on.kafka_broken.emit()
-
-    @property
-    def host(self) -> str:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            relation.data[relation.app].get(KAFKA_HOST_APP_KEY)
-            if relation and relation.app
-            else None
-        )
-
-    @property
-    def port(self) -> int:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            int(relation.data[relation.app].get(KAFKA_PORT_APP_KEY))
-            if relation and relation.app
-            else None
-        )
-
-
-class KafkaProvides(Object):
-    """Provides-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self._endpoint_name = endpoint_name
-
-    def set_host_info(self, host: str, port: int, relation: Optional[Relation] = None) -> None:
-        """Set Kafka host and port.
-
-        This function writes in the application data of the relation, therefore,
-        only the unit leader can call it.
-
-        Args:
-            host (str): Kafka hostname or IP address.
-            port (int): Kafka port.
-            relation (Optional[Relation]): Relation to update.
-                                           If not specified, all relations will be updated.
-
-        Raises:
-            Exception: if a non-leader unit calls this function.
-        """
-        if not self.model.unit.is_leader():
-            raise Exception("only the leader set host information.")
-
-        if relation:
-            self._update_relation_data(host, port, relation)
-            return
-
-        for relation in self.model.relations[self._endpoint_name]:
-            self._update_relation_data(host, port, relation)
-
-    def _update_relation_data(self, host: str, port: int, relation: Relation) -> None:
-        """Update data in relation if needed."""
-        relation.data[self.model.app][KAFKA_HOST_APP_KEY] = host
-        relation.data[self.model.app][KAFKA_PORT_APP_KEY] = str(port)
diff --git a/installers/charm/mon/metadata.yaml b/installers/charm/mon/metadata.yaml
deleted file mode 100644 (file)
index f3c3990..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-name: osm-mon
-summary: OSM Monitoring (MON)
-description: |
-  A CAAS charm to deploy OSM's Monitoring (MON).
-series:
-  - kubernetes
-tags:
-  - kubernetes
-  - osm
-  - mon
-min-juju-version: 2.8.0
-deployment:
-  type: stateless
-  service: cluster
-resources:
-  image:
-    type: oci-image
-    description: OSM docker image for MON
-    upstream-source: "opensourcemano/mon:latest"
-requires:
-  kafka:
-    interface: kafka
-  mongodb:
-    interface: mongodb
-  prometheus:
-    interface: prometheus
-  keystone:
-    interface: keystone
diff --git a/installers/charm/mon/requirements-test.txt b/installers/charm/mon/requirements-test.txt
deleted file mode 100644 (file)
index cf61dd4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-mock==4.0.3
diff --git a/installers/charm/mon/requirements.txt b/installers/charm/mon/requirements.txt
deleted file mode 100644 (file)
index 1a8928c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master
\ No newline at end of file
diff --git a/installers/charm/mon/src/charm.py b/installers/charm/mon/src/charm.py
deleted file mode 100755 (executable)
index 9ad49ad..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213
-
-
-import base64
-import logging
-from typing import NoReturn, Optional
-
-
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.main import main
-from opslib.osm.charm import CharmedOsmBase, RelationsMissing
-from opslib.osm.interfaces.keystone import KeystoneClient
-from opslib.osm.interfaces.mongo import MongoClient
-from opslib.osm.interfaces.prometheus import PrometheusClient
-from opslib.osm.pod import (
-    ContainerV3Builder,
-    FilesV3Builder,
-    PodRestartPolicy,
-    PodSpecV3Builder,
-)
-from opslib.osm.validator import ModelValidator, validator
-
-
-logger = logging.getLogger(__name__)
-
-PORT = 8000
-
-
-def _check_certificate_data(name: str, content: str):
-    if not name or not content:
-        raise ValueError("certificate name and content must be a non-empty string")
-
-
-def _extract_certificates(certs_config: str):
-    certificates = {}
-    if certs_config:
-        cert_list = certs_config.split(",")
-        for cert in cert_list:
-            name, content = cert.split(":")
-            _check_certificate_data(name, content)
-            certificates[name] = content
-    return certificates
-
-
-def decode(content: str):
-    return base64.b64decode(content.encode("utf-8")).decode("utf-8")
-
-
-class ConfigModel(ModelValidator):
-    keystone_enabled: bool
-    vca_host: str
-    vca_user: str
-    vca_secret: str
-    vca_cacert: str
-    database_commonkey: str
-    mongodb_uri: Optional[str]
-    log_level: str
-    openstack_default_granularity: int
-    global_request_timeout: int
-    collector_interval: int
-    vm_infra_metrics: bool
-    evaluator_interval: int
-    grafana_url: str
-    grafana_user: str
-    grafana_password: str
-    certificates: Optional[str]
-    image_pull_policy: str
-    debug_mode: bool
-    security_context: bool
-
-    @validator("log_level")
-    def validate_log_level(cls, v):
-        if v not in {"INFO", "DEBUG"}:
-            raise ValueError("value must be INFO or DEBUG")
-        return v
-
-    @validator("certificates")
-    def validate_certificates(cls, v):
-        # Raises an exception if it cannot extract the certificates
-        _extract_certificates(v)
-        return v
-
-    @validator("mongodb_uri")
-    def validate_mongodb_uri(cls, v):
-        if v and not v.startswith("mongodb://"):
-            raise ValueError("mongodb_uri is not properly formed")
-        return v
-
-    @validator("image_pull_policy")
-    def validate_image_pull_policy(cls, v):
-        values = {
-            "always": "Always",
-            "ifnotpresent": "IfNotPresent",
-            "never": "Never",
-        }
-        v = v.lower()
-        if v not in values.keys():
-            raise ValueError("value must be always, ifnotpresent or never")
-        return values[v]
-
-    @property
-    def certificates_dict(cls):
-        return _extract_certificates(cls.certificates) if cls.certificates else {}
-
-
-class MonCharm(CharmedOsmBase):
-    on = KafkaEvents()
-
-    def __init__(self, *args) -> NoReturn:
-        super().__init__(
-            *args,
-            oci_image="image",
-            vscode_workspace=VSCODE_WORKSPACE,
-        )
-        if self.config.get("debug_mode"):
-            self.enable_debug_mode(
-                pubkey=self.config.get("debug_pubkey"),
-                hostpaths={
-                    "MON": {
-                        "hostpath": self.config.get("debug_mon_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_mon",
-                    },
-                    "N2VC": {
-                        "hostpath": self.config.get("debug_n2vc_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/n2vc",
-                    },
-                    "osm_common": {
-                        "hostpath": self.config.get("debug_common_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_common",
-                    },
-                },
-            )
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(self.on.kafka_available, self.configure_pod)
-        self.framework.observe(self.on.kafka_broken, self.configure_pod)
-
-        self.mongodb_client = MongoClient(self, "mongodb")
-        self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
-
-        self.prometheus_client = PrometheusClient(self, "prometheus")
-        self.framework.observe(
-            self.on["prometheus"].relation_changed, self.configure_pod
-        )
-        self.framework.observe(
-            self.on["prometheus"].relation_broken, self.configure_pod
-        )
-
-        self.keystone_client = KeystoneClient(self, "keystone")
-        self.framework.observe(self.on["keystone"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["keystone"].relation_broken, self.configure_pod)
-
-    def _check_missing_dependencies(self, config: ConfigModel):
-        missing_relations = []
-
-        if not self.kafka.host or not self.kafka.port:
-            missing_relations.append("kafka")
-        if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
-            missing_relations.append("mongodb")
-        if self.prometheus_client.is_missing_data_in_app():
-            missing_relations.append("prometheus")
-        if config.keystone_enabled:
-            if self.keystone_client.is_missing_data_in_app():
-                missing_relations.append("keystone")
-
-        if missing_relations:
-            raise RelationsMissing(missing_relations)
-
-    def _build_cert_files(
-        self,
-        config: ConfigModel,
-    ):
-        cert_files_builder = FilesV3Builder()
-        for name, content in config.certificates_dict.items():
-            cert_files_builder.add_file(name, decode(content), mode=0o600)
-        return cert_files_builder.build()
-
-    def build_pod_spec(self, image_info):
-        # Validate config
-        config = ConfigModel(**dict(self.config))
-
-        if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
-            raise Exception("Mongodb data cannot be provided via config and relation")
-
-        # Check relations
-        self._check_missing_dependencies(config)
-
-        security_context_enabled = (
-            config.security_context if not config.debug_mode else False
-        )
-
-        # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder(
-            enable_security_context=security_context_enabled
-        )
-
-        # Add secrets to the pod
-        mongodb_secret_name = f"{self.app.name}-mongodb-secret"
-        pod_spec_builder.add_secret(
-            mongodb_secret_name,
-            {
-                "uri": config.mongodb_uri or self.mongodb_client.connection_string,
-                "commonkey": config.database_commonkey,
-            },
-        )
-        grafana_secret_name = f"{self.app.name}-grafana-secret"
-        pod_spec_builder.add_secret(
-            grafana_secret_name,
-            {
-                "url": config.grafana_url,
-                "user": config.grafana_user,
-                "password": config.grafana_password,
-            },
-        )
-
-        vca_secret_name = f"{self.app.name}-vca-secret"
-        pod_spec_builder.add_secret(
-            vca_secret_name,
-            {
-                "host": config.vca_host,
-                "user": config.vca_user,
-                "secret": config.vca_secret,
-                "cacert": config.vca_cacert,
-            },
-        )
-
-        # Build Container
-        container_builder = ContainerV3Builder(
-            self.app.name,
-            image_info,
-            config.image_pull_policy,
-            run_as_non_root=security_context_enabled,
-        )
-        certs_files = self._build_cert_files(config)
-
-        if certs_files:
-            container_builder.add_volume_config("certs", "/certs", certs_files)
-
-        container_builder.add_port(name=self.app.name, port=PORT)
-        container_builder.add_envs(
-            {
-                # General configuration
-                "ALLOW_ANONYMOUS_LOGIN": "yes",
-                "OSMMON_OPENSTACK_DEFAULT_GRANULARITY": config.openstack_default_granularity,
-                "OSMMON_GLOBAL_REQUEST_TIMEOUT": config.global_request_timeout,
-                "OSMMON_GLOBAL_LOGLEVEL": config.log_level,
-                "OSMMON_COLLECTOR_INTERVAL": config.collector_interval,
-                "OSMMON_COLLECTOR_VM_INFRA_METRICS": config.vm_infra_metrics,
-                "OSMMON_EVALUATOR_INTERVAL": config.evaluator_interval,
-                # Kafka configuration
-                "OSMMON_MESSAGE_DRIVER": "kafka",
-                "OSMMON_MESSAGE_HOST": self.kafka.host,
-                "OSMMON_MESSAGE_PORT": self.kafka.port,
-                # Database configuration
-                "OSMMON_DATABASE_DRIVER": "mongo",
-                # Prometheus configuration
-                "OSMMON_PROMETHEUS_URL": f"http://{self.prometheus_client.hostname}:{self.prometheus_client.port}",
-            }
-        )
-        prometheus_user = self.prometheus_client.user
-        prometheus_password = self.prometheus_client.password
-        if prometheus_user and prometheus_password:
-            container_builder.add_envs(
-                {
-                    "OSMMON_PROMETHEUS_USER": prometheus_user,
-                    "OSMMON_PROMETHEUS_PASSWORD": prometheus_password,
-                }
-            )
-        container_builder.add_secret_envs(
-            secret_name=mongodb_secret_name,
-            envs={
-                "OSMMON_DATABASE_URI": "uri",
-                "OSMMON_DATABASE_COMMONKEY": "commonkey",
-            },
-        )
-        container_builder.add_secret_envs(
-            secret_name=vca_secret_name,
-            envs={
-                "OSMMON_VCA_HOST": "host",
-                "OSMMON_VCA_USER": "user",
-                "OSMMON_VCA_SECRET": "secret",
-                "OSMMON_VCA_CACERT": "cacert",
-            },
-        )
-        container_builder.add_secret_envs(
-            secret_name=grafana_secret_name,
-            envs={
-                "OSMMON_GRAFANA_URL": "url",
-                "OSMMON_GRAFANA_USER": "user",
-                "OSMMON_GRAFANA_PASSWORD": "password",
-            },
-        )
-        if config.keystone_enabled:
-            keystone_secret_name = f"{self.app.name}-keystone-secret"
-            pod_spec_builder.add_secret(
-                keystone_secret_name,
-                {
-                    "url": self.keystone_client.host,
-                    "user_domain": self.keystone_client.user_domain_name,
-                    "project_domain": self.keystone_client.project_domain_name,
-                    "service_username": self.keystone_client.username,
-                    "service_password": self.keystone_client.password,
-                    "service_project": self.keystone_client.service,
-                },
-            )
-            container_builder.add_env("OSMMON_KEYSTONE_ENABLED", True)
-            container_builder.add_secret_envs(
-                secret_name=keystone_secret_name,
-                envs={
-                    "OSMMON_KEYSTONE_URL": "url",
-                    "OSMMON_KEYSTONE_DOMAIN_NAME": "user_domain",
-                    "OSMMON_KEYSTONE_PROJECT_DOMAIN_NAME": "project_domain",
-                    "OSMMON_KEYSTONE_SERVICE_USER": "service_username",
-                    "OSMMON_KEYSTONE_SERVICE_PASSWORD": "service_password",
-                    "OSMMON_KEYSTONE_SERVICE_PROJECT": "service_project",
-                },
-            )
-        container = container_builder.build()
-
-        # Add restart policy
-        restart_policy = PodRestartPolicy()
-        restart_policy.add_secrets()
-        pod_spec_builder.set_restart_policy(restart_policy)
-
-        # Add container to pod spec
-        pod_spec_builder.add_container(container)
-
-        return pod_spec_builder.build()
-
-
-VSCODE_WORKSPACE = {
-    "folders": [
-        {"path": "/usr/lib/python3/dist-packages/osm_mon"},
-        {"path": "/usr/lib/python3/dist-packages/osm_common"},
-        {"path": "/usr/lib/python3/dist-packages/n2vc"},
-    ],
-    "settings": {},
-    "launch": {
-        "version": "0.2.0",
-        "configurations": [
-            {
-                "name": "MON Server",
-                "type": "python",
-                "request": "launch",
-                "module": "osm_mon.cmd.mon_server",
-                "justMyCode": False,
-            },
-            {
-                "name": "MON evaluator",
-                "type": "python",
-                "request": "launch",
-                "module": "osm_mon.cmd.mon_evaluator",
-                "justMyCode": False,
-            },
-            {
-                "name": "MON collector",
-                "type": "python",
-                "request": "launch",
-                "module": "osm_mon.cmd.mon_collector",
-                "justMyCode": False,
-            },
-            {
-                "name": "MON dashboarder",
-                "type": "python",
-                "request": "launch",
-                "module": "osm_mon.cmd.mon_dashboarder",
-                "justMyCode": False,
-            },
-        ],
-    },
-}
-if __name__ == "__main__":
-    main(MonCharm)
diff --git a/installers/charm/mon/src/pod_spec.py b/installers/charm/mon/src/pod_spec.py
deleted file mode 100644 (file)
index dcadfc0..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import logging
-from typing import Any, Dict, List, NoReturn
-
-logger = logging.getLogger(__name__)
-
-
-def _validate_data(
-    config_data: Dict[str, Any], relation_data: Dict[str, Any]
-) -> NoReturn:
-    """Validate input data.
-
-    Args:
-        config_data (Dict[str, Any]): configuration data.
-        relation_data (Dict[str, Any]): relation data.
-    """
-    config_validators = {
-        "openstack_default_granularity": lambda value, _: (
-            isinstance(value, int) and value > 0
-        ),
-        "global_request_timeout": lambda value, _: isinstance(value, int) and value > 0,
-        "log_level": lambda value, _: (
-            isinstance(value, str) and value in ("INFO", "DEBUG")
-        ),
-        "collector_interval": lambda value, _: isinstance(value, int) and value > 0,
-        "evaluator_interval": lambda value, _: isinstance(value, int) and value > 0,
-        "database_commonkey": lambda value, _: (
-            isinstance(value, str) and len(value) > 0
-        ),
-        "vca_host": lambda value, _: isinstance(value, str) and len(value) > 0,
-        "vca_user": lambda value, _: isinstance(value, str) and len(value) > 0,
-        "vca_password": lambda value, _: isinstance(value, str) and len(value) > 0,
-        "vca_cacert": lambda value, _: isinstance(value, str),
-    }
-    relation_validators = {
-        "message_host": lambda value, _: isinstance(value, str) and len(value) > 0,
-        "message_port": lambda value, _: isinstance(value, int) and value > 0,
-        "database_uri": lambda value, _: (
-            isinstance(value, str) and value.startswith("mongodb://")
-        ),
-        "prometheus_host": lambda value, _: isinstance(value, str) and len(value) > 0,
-        "prometheus_port": lambda value, _: isinstance(value, int) and value > 0,
-    }
-    problems = []
-
-    for key, validator in config_validators.items():
-        valid = validator(config_data.get(key), config_data)
-
-        if not valid:
-            problems.append(key)
-
-    for key, validator in relation_validators.items():
-        valid = validator(relation_data.get(key), relation_data)
-
-        if not valid:
-            problems.append(key)
-
-    if len(problems) > 0:
-        raise ValueError("Errors found in: {}".format(", ".join(problems)))
-
-
-def _make_pod_ports(port: int) -> List[Dict[str, Any]]:
-    """Generate pod ports details.
-
-    Args:
-        port (int): port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod port details.
-    """
-    return [{"name": "mon", "containerPort": port, "protocol": "TCP"}]
-
-
-def _make_pod_envconfig(
-    config: Dict[str, Any], relation_state: Dict[str, Any]
-) -> Dict[str, Any]:
-    """Generate pod environment configuration.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-        relation_state (Dict[str, Any]): relation state information.
-
-    Returns:
-        Dict[str, Any]: pod environment configuration.
-    """
-    envconfig = {
-        # General configuration
-        "ALLOW_ANONYMOUS_LOGIN": "yes",
-        "OSMMON_OPENSTACK_DEFAULT_GRANULARITY": config["openstack_default_granularity"],
-        "OSMMON_GLOBAL_REQUEST_TIMEOUT": config["global_request_timeout"],
-        "OSMMON_GLOBAL_LOGLEVEL": config["log_level"],
-        "OSMMON_COLLECTOR_INTERVAL": config["collector_interval"],
-        "OSMMON_EVALUATOR_INTERVAL": config["evaluator_interval"],
-        # Kafka configuration
-        "OSMMON_MESSAGE_DRIVER": "kafka",
-        "OSMMON_MESSAGE_HOST": relation_state["message_host"],
-        "OSMMON_MESSAGE_PORT": relation_state["message_port"],
-        # Database configuration
-        "OSMMON_DATABASE_DRIVER": "mongo",
-        "OSMMON_DATABASE_URI": relation_state["database_uri"],
-        "OSMMON_DATABASE_COMMONKEY": config["database_commonkey"],
-        # Prometheus configuration
-        "OSMMON_PROMETHEUS_URL": f"http://{relation_state['prometheus_host']}:{relation_state['prometheus_port']}",
-        # VCA configuration
-        "OSMMON_VCA_HOST": config["vca_host"],
-        "OSMMON_VCA_USER": config["vca_user"],
-        "OSMMON_VCA_SECRET": config["vca_password"],
-        "OSMMON_VCA_CACERT": config["vca_cacert"],
-    }
-
-    return envconfig
-
-
-def _make_startup_probe() -> Dict[str, Any]:
-    """Generate startup probe.
-
-    Returns:
-        Dict[str, Any]: startup probe.
-    """
-    return {
-        "exec": {"command": ["/usr/bin/pgrep python3"]},
-        "initialDelaySeconds": 60,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_readiness_probe(port: int) -> Dict[str, Any]:
-    """Generate readiness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: readiness probe.
-    """
-    return {
-        "tcpSocket": {
-            "port": port,
-        },
-        "periodSeconds": 10,
-        "timeoutSeconds": 5,
-        "successThreshold": 1,
-        "failureThreshold": 3,
-    }
-
-
-def _make_liveness_probe(port: int) -> Dict[str, Any]:
-    """Generate liveness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: liveness probe.
-    """
-    return {
-        "tcpSocket": {
-            "port": port,
-        },
-        "initialDelaySeconds": 45,
-        "periodSeconds": 10,
-        "timeoutSeconds": 5,
-        "successThreshold": 1,
-        "failureThreshold": 3,
-    }
-
-
-def make_pod_spec(
-    image_info: Dict[str, str],
-    config: Dict[str, Any],
-    relation_state: Dict[str, Any],
-    app_name: str = "mon",
-    port: int = 8000,
-) -> Dict[str, Any]:
-    """Generate the pod spec information.
-
-    Args:
-        image_info (Dict[str, str]): Object provided by
-                                     OCIImageResource("image").fetch().
-        config (Dict[str, Any]): Configuration information.
-        relation_state (Dict[str, Any]): Relation state information.
-        app_name (str, optional): Application name. Defaults to "mon".
-        port (int, optional): Port for the container. Defaults to 8000.
-
-    Returns:
-        Dict[str, Any]: Pod spec dictionary for the charm.
-    """
-    if not image_info:
-        return None
-
-    _validate_data(config, relation_state)
-
-    ports = _make_pod_ports(port)
-    env_config = _make_pod_envconfig(config, relation_state)
-
-    return {
-        "version": 3,
-        "containers": [
-            {
-                "name": app_name,
-                "imageDetails": image_info,
-                "imagePullPolicy": "Always",
-                "ports": ports,
-                "envConfig": env_config,
-            }
-        ],
-        "kubernetesResources": {
-            "ingressResources": [],
-        },
-    }
diff --git a/installers/charm/mon/tests/__init__.py b/installers/charm/mon/tests/__init__.py
deleted file mode 100644 (file)
index 446d5ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-"""Init mocking for unit tests."""
-
-import sys
-
-
-import mock
-
-
-class OCIImageResourceErrorMock(Exception):
-    pass
-
-
-sys.path.append("src")
-
-oci_image = mock.MagicMock()
-oci_image.OCIImageResourceError = OCIImageResourceErrorMock
-sys.modules["oci_image"] = oci_image
-sys.modules["oci_image"].OCIImageResource().fetch.return_value = {}
diff --git a/installers/charm/mon/tests/test_charm.py b/installers/charm/mon/tests/test_charm.py
deleted file mode 100644 (file)
index e9748d3..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import base64
-import sys
-from typing import NoReturn
-import unittest
-
-from charm import MonCharm
-from ops.model import ActiveStatus, BlockedStatus
-from ops.testing import Harness
-
-
-def encode(content: str):
-    return base64.b64encode(content.encode("ascii")).decode("utf-8")
-
-
-certificate_pem = encode(
-    """
------BEGIN CERTIFICATE-----
-MIIDazCCAlOgAwIBAgIUf1b0s3UKtrxHXH2rge7UaQyfJAMwDQYJKoZIhvcNAQEL
-BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
-GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTAzMjIxNzEyMjdaFw0zMTAz
-MjAxNzEyMjdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
-HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQCgCfCBgYAN6ON0yHDXuW407rFtJVRf0u46Jrp0Dk7J
-kkSZ1e7Kq14r7yFHazEBWv78oOdwBocvWrd8leLuf3bYGcHR65hRy6A/fbYm5Aje
-cKpwlFwaqfR4BLelwJl79jZ2rJX738cCBVrIk1nAVdOxGrXV4MTWUaKR2c+uKKvc
-OKRT+5VqCeP4N5FWeATZ/KqGu8uV9E9WhFgwIZyStemLyLaDbn5PmAQ6S9oeR5jJ
-o2gEEp/lDKvsqOWs76KFumSKa9hQs5Dw2lj0mb1UoyYK1gYc4ubzVChJadv44AU8
-MYtIjlFn1X1P+RjaKZNUIAGXkoLwYn6SizF6y6LiuFS9AgMBAAGjUzBRMB0GA1Ud
-DgQWBBRl+/23CB+FXczeAZRQyYcfOdy9YDAfBgNVHSMEGDAWgBRl+/23CB+FXcze
-AZRQyYcfOdy9YDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAd
-dkeDym6lRN8kWFtfu3IyiLF8G8sn91qNbH3Yr4TuTBhgcjYyW6PgisSbrNgA9ysE
-GoaF7ohb8GeVfCsQdK23+NpAlj/+DZ3OnGcxwXj1RUAz4yr9kanV1yuEtr1q2xJI
-UaECWr8HZlwGBAKNTGx2EXT2/2aFzgULpDcxzTKD+MRpKpMUrWhf9ULvVrclvHWe
-POLYhobUFuBHuo6rt5Rcq16j67zCX9EVTlAE3o2OECIWByK22sXdeOidYMpTkl4q
-8FrOqjNsx5d+SBPJBv/pqtBm4bA47Vx1P8tbWOQ4bXS0UmXgwpeBOU/O/ot30+KS
-JnKEy+dYyvVBKg77sRHw
------END CERTIFICATE-----
-"""
-)
-
-
-class TestCharm(unittest.TestCase):
-    """Prometheus Charm unit tests."""
-
-    def setUp(self) -> NoReturn:
-        """Test setup"""
-        self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
-        self.harness = Harness(MonCharm)
-        self.harness.set_leader(is_leader=True)
-        self.harness.begin()
-        self.config = {
-            "vca_host": "192.168.0.13",
-            "vca_user": "admin",
-            "vca_secret": "admin",
-            "vca_cacert": "cacert",
-            "database_commonkey": "commonkey",
-            "mongodb_uri": "",
-            "log_level": "INFO",
-            "openstack_default_granularity": 10,
-            "global_request_timeout": 10,
-            "collector_interval": 30,
-            "evaluator_interval": 30,
-            "keystone_enabled": True,
-            "certificates": f"cert1:{certificate_pem}",
-        }
-        self.harness.update_config(self.config)
-
-    def test_config_changed_no_relations(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["mongodb", "kafka", "prometheus", "keystone"]
-            )
-        )
-
-    def test_config_changed_non_leader(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-        self.harness.set_leader(is_leader=False)
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-    def test_with_relations_and_mongodb_config(
-        self,
-    ) -> NoReturn:
-        "Test with relations (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_config()
-        self.initialize_prometheus_relation()
-        self.initialize_keystone_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations(
-        self,
-    ) -> NoReturn:
-        "Test with relations (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_prometheus_relation()
-        self.initialize_keystone_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_exception_mongodb_relation_and_config(
-        self,
-    ) -> NoReturn:
-        "Test with relations and config for mongodb. Must fail"
-        self.initialize_mongo_relation()
-        self.initialize_mongo_config()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def initialize_kafka_relation(self):
-        kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-        self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-        self.harness.update_relation_data(
-            kafka_relation_id, "kafka", {"host": "kafka", "port": 9092}
-        )
-
-    def initialize_mongo_config(self):
-        self.harness.update_config({"mongodb_uri": "mongodb://mongo:27017"})
-
-    def initialize_mongo_relation(self):
-        mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-        self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mongodb/0",
-            {"connection_string": "mongodb://mongo:27017"},
-        )
-
-    def initialize_prometheus_relation(self):
-        prometheus_relation_id = self.harness.add_relation("prometheus", "prometheus")
-        self.harness.add_relation_unit(prometheus_relation_id, "prometheus/0")
-        self.harness.update_relation_data(
-            prometheus_relation_id,
-            "prometheus",
-            {"hostname": "prometheus", "port": 9090},
-        )
-
-    def initialize_keystone_relation(self):
-        keystone_relation_id = self.harness.add_relation("keystone", "keystone")
-        self.harness.add_relation_unit(keystone_relation_id, "keystone/0")
-        self.harness.update_relation_data(
-            keystone_relation_id,
-            "keystone",
-            {
-                "host": "host",
-                "port": 5000,
-                "user_domain_name": "ud",
-                "project_domain_name": "pd",
-                "username": "u",
-                "password": "p",
-                "service": "s",
-                "keystone_db_password": "something",
-                "region_id": "something",
-                "admin_username": "something",
-                "admin_password": "something",
-                "admin_project_name": "something",
-            },
-        )
-
-
-if __name__ == "__main__":
-    unittest.main()
-
-
-# class TestCharm(unittest.TestCase):
-#     """MON Charm unit tests."""
-
-#     def setUp(self) -> NoReturn:
-#         """Test setup"""
-#         self.harness = Harness(MonCharm)
-#         self.harness.set_leader(is_leader=True)
-#         self.harness.begin()
-
-#     def test_on_start_without_relations(self) -> NoReturn:
-#         """Test installation without any relation."""
-#         self.harness.charm.on.start.emit()
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertIn("prometheus", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_start_with_relations(self) -> NoReturn:
-#         """Test deployment without keystone."""
-#         expected_result = {
-#             "version": 3,
-#             "containers": [
-#                 {
-#                     "name": "mon",
-#                     "imageDetails": self.harness.charm.image.fetch(),
-#                     "imagePullPolicy": "Always",
-#                     "ports": [
-#                         {
-#                             "name": "mon",
-#                             "containerPort": 8000,
-#                             "protocol": "TCP",
-#                         }
-#                     ],
-#                     "envConfig": {
-#                         "ALLOW_ANONYMOUS_LOGIN": "yes",
-#                         "OSMMON_OPENSTACK_DEFAULT_GRANULARITY": 300,
-#                         "OSMMON_GLOBAL_REQUEST_TIMEOUT": 10,
-#                         "OSMMON_GLOBAL_LOGLEVEL": "INFO",
-#                         "OSMMON_COLLECTOR_INTERVAL": 30,
-#                         "OSMMON_EVALUATOR_INTERVAL": 30,
-#                         "OSMMON_MESSAGE_DRIVER": "kafka",
-#                         "OSMMON_MESSAGE_HOST": "kafka",
-#                         "OSMMON_MESSAGE_PORT": 9092,
-#                         "OSMMON_DATABASE_DRIVER": "mongo",
-#                         "OSMMON_DATABASE_URI": "mongodb://mongo:27017",
-#                         "OSMMON_DATABASE_COMMONKEY": "osm",
-#                         "OSMMON_PROMETHEUS_URL": "http://prometheus:9090",
-#                         "OSMMON_VCA_HOST": "admin",
-#                         "OSMMON_VCA_USER": "admin",
-#                         "OSMMON_VCA_SECRET": "secret",
-#                         "OSMMON_VCA_CACERT": "",
-#                     },
-#                 }
-#             ],
-#             "kubernetesResources": {"ingressResources": []},
-#         }
-
-#         self.harness.charm.on.start.emit()
-
-#         # Check if kafka datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.message_host)
-#         self.assertIsNone(self.harness.charm.state.message_port)
-
-#         # Check if mongodb datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.database_uri)
-
-#         # Check if prometheus datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.prometheus_host)
-#         self.assertIsNone(self.harness.charm.state.prometheus_port)
-
-#         # Initializing the kafka relation
-#         kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             kafka_relation_id, "kafka/0", {"host": "kafka", "port": 9092}
-#         )
-
-#         # Initializing the mongo relation
-#         mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             mongodb_relation_id,
-#             "mongodb/0",
-#             {"connection_string": "mongodb://mongo:27017"},
-#         )
-
-#         # Initializing the prometheus relation
-#         prometheus_relation_id = self.harness.add_relation("prometheus", "prometheus")
-#         self.harness.add_relation_unit(prometheus_relation_id, "prometheus/0")
-#         self.harness.update_relation_data(
-#             prometheus_relation_id,
-#             "prometheus",
-#             {"hostname": "prometheus", "port": 9090},
-#         )
-
-#         # Checking if kafka data is stored
-#         self.assertEqual(self.harness.charm.state.message_host, "kafka")
-#         self.assertEqual(self.harness.charm.state.message_port, 9092)
-
-#         # Checking if mongodb data is stored
-#         self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
-
-#         # Checking if prometheus data is stored
-#         self.assertEqual(self.harness.charm.state.prometheus_host, "prometheus")
-#         self.assertEqual(self.harness.charm.state.prometheus_port, 9090)
-
-#         # Verifying status
-#         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         pod_spec, _ = self.harness.get_pod_spec()
-
-#         self.assertDictEqual(expected_result, pod_spec)
-
-#     def test_on_kafka_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if kafka relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.message_host)
-#         self.assertIsNone(self.harness.charm.state.message_port)
-
-#         relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             relation_id, "kafka/0", {"host": "kafka", "port": 9092}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.message_host, "kafka")
-#         self.assertEqual(self.harness.charm.state.message_port, 9092)
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertNotIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertIn("prometheus", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_mongodb_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if mongodb relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.database_uri)
-
-#         relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             relation_id, "mongodb/0", {"connection_string": "mongodb://mongo:27017"}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertNotIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertIn("prometheus", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_prometheus_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if prometheus relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.prometheus_host)
-#         self.assertIsNone(self.harness.charm.state.prometheus_port)
-
-#         relation_id = self.harness.add_relation("prometheus", "prometheus")
-#         self.harness.add_relation_unit(relation_id, "prometheus/0")
-#         self.harness.update_relation_data(
-#             relation_id, "prometheus", {"hostname": "prometheus", "port": 9090}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.prometheus_host, "prometheus")
-#         self.assertEqual(self.harness.charm.state.prometheus_port, 9090)
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertNotIn("prometheus", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-
-# if __name__ == "__main__":
-#     unittest.main()
diff --git a/installers/charm/mon/tests/test_pod_spec.py b/installers/charm/mon/tests/test_pod_spec.py
deleted file mode 100644 (file)
index 86a3d16..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-from typing import NoReturn
-import unittest
-
-import pod_spec
-
-
-class TestPodSpec(unittest.TestCase):
-    """Pod spec unit tests."""
-
-    def test_make_pod_ports(self) -> NoReturn:
-        """Testing make pod ports."""
-        port = 8000
-
-        expected_result = [
-            {
-                "name": "mon",
-                "containerPort": port,
-                "protocol": "TCP",
-            }
-        ]
-
-        pod_ports = pod_spec._make_pod_ports(port)
-
-        self.assertListEqual(expected_result, pod_ports)
-
-    def test_make_pod_envconfig(self) -> NoReturn:
-        """Testing make pod envconfig."""
-        config = {
-            "openstack_default_granularity": 300,
-            "global_request_timeout": 10,
-            "log_level": "INFO",
-            "database_commonkey": "osm",
-            "collector_interval": 30,
-            "evaluator_interval": 30,
-            "vca_host": "admin",
-            "vca_user": "admin",
-            "vca_password": "secret",
-            "vca_cacert": "",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-
-        expected_result = {
-            "ALLOW_ANONYMOUS_LOGIN": "yes",
-            "OSMMON_OPENSTACK_DEFAULT_GRANULARITY": config[
-                "openstack_default_granularity"
-            ],
-            "OSMMON_GLOBAL_REQUEST_TIMEOUT": config["global_request_timeout"],
-            "OSMMON_GLOBAL_LOGLEVEL": config["log_level"],
-            "OSMMON_COLLECTOR_INTERVAL": config["collector_interval"],
-            "OSMMON_EVALUATOR_INTERVAL": config["evaluator_interval"],
-            "OSMMON_MESSAGE_DRIVER": "kafka",
-            "OSMMON_MESSAGE_HOST": relation_state["message_host"],
-            "OSMMON_MESSAGE_PORT": relation_state["message_port"],
-            "OSMMON_DATABASE_DRIVER": "mongo",
-            "OSMMON_DATABASE_URI": relation_state["database_uri"],
-            "OSMMON_DATABASE_COMMONKEY": config["database_commonkey"],
-            "OSMMON_PROMETHEUS_URL": f"http://{relation_state['prometheus_host']}:{relation_state['prometheus_port']}",
-            "OSMMON_VCA_HOST": config["vca_host"],
-            "OSMMON_VCA_USER": config["vca_user"],
-            "OSMMON_VCA_SECRET": config["vca_password"],
-            "OSMMON_VCA_CACERT": config["vca_cacert"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_startup_probe(self) -> NoReturn:
-        """Testing make startup probe."""
-        expected_result = {
-            "exec": {"command": ["/usr/bin/pgrep python3"]},
-            "initialDelaySeconds": 60,
-            "timeoutSeconds": 5,
-        }
-
-        startup_probe = pod_spec._make_startup_probe()
-
-        self.assertDictEqual(expected_result, startup_probe)
-
-    def test_make_readiness_probe(self) -> NoReturn:
-        """Testing make readiness probe."""
-        port = 8000
-
-        expected_result = {
-            "tcpSocket": {
-                "port": port,
-            },
-            "periodSeconds": 10,
-            "timeoutSeconds": 5,
-            "successThreshold": 1,
-            "failureThreshold": 3,
-        }
-
-        readiness_probe = pod_spec._make_readiness_probe(port)
-
-        self.assertDictEqual(expected_result, readiness_probe)
-
-    def test_make_liveness_probe(self) -> NoReturn:
-        """Testing make liveness probe."""
-        port = 8000
-
-        expected_result = {
-            "tcpSocket": {
-                "port": port,
-            },
-            "initialDelaySeconds": 45,
-            "periodSeconds": 10,
-            "timeoutSeconds": 5,
-            "successThreshold": 1,
-            "failureThreshold": 3,
-        }
-
-        liveness_probe = pod_spec._make_liveness_probe(port)
-
-        self.assertDictEqual(expected_result, liveness_probe)
-
-    def test_make_pod_spec(self) -> NoReturn:
-        """Testing make pod spec."""
-        image_info = {"upstream-source": "opensourcemano/mon:8"}
-        config = {
-            "site_url": "",
-            "openstack_default_granularity": 300,
-            "global_request_timeout": 10,
-            "log_level": "INFO",
-            "database_commonkey": "osm",
-            "collector_interval": 30,
-            "evaluator_interval": 30,
-            "vca_host": "admin",
-            "vca_user": "admin",
-            "vca_password": "secret",
-            "vca_cacert": "",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-        app_name = "mon"
-        port = 8000
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": app_name,
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "ALLOW_ANONYMOUS_LOGIN": "yes",
-                        "OSMMON_OPENSTACK_DEFAULT_GRANULARITY": config[
-                            "openstack_default_granularity"
-                        ],
-                        "OSMMON_GLOBAL_REQUEST_TIMEOUT": config[
-                            "global_request_timeout"
-                        ],
-                        "OSMMON_GLOBAL_LOGLEVEL": config["log_level"],
-                        "OSMMON_COLLECTOR_INTERVAL": config["collector_interval"],
-                        "OSMMON_EVALUATOR_INTERVAL": config["evaluator_interval"],
-                        "OSMMON_MESSAGE_DRIVER": "kafka",
-                        "OSMMON_MESSAGE_HOST": relation_state["message_host"],
-                        "OSMMON_MESSAGE_PORT": relation_state["message_port"],
-                        "OSMMON_DATABASE_DRIVER": "mongo",
-                        "OSMMON_DATABASE_URI": relation_state["database_uri"],
-                        "OSMMON_DATABASE_COMMONKEY": config["database_commonkey"],
-                        "OSMMON_PROMETHEUS_URL": (
-                            f"http://{relation_state['prometheus_host']}:{relation_state['prometheus_port']}"
-                        ),
-                        "OSMMON_VCA_HOST": config["vca_host"],
-                        "OSMMON_VCA_USER": config["vca_user"],
-                        "OSMMON_VCA_SECRET": config["vca_password"],
-                        "OSMMON_VCA_CACERT": config["vca_cacert"],
-                    },
-                }
-            ],
-            "kubernetesResources": {"ingressResources": []},
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-    def test_make_pod_spec_without_image_info(self) -> NoReturn:
-        """Testing make pod spec without image_info."""
-        image_info = None
-        config = {
-            "site_url": "",
-            "openstack_default_granularity": 300,
-            "global_request_timeout": 10,
-            "log_level": "INFO",
-            "database_commonkey": "osm",
-            "collector_interval": 30,
-            "evaluator_interval": 30,
-            "vca_host": "admin",
-            "vca_user": "admin",
-            "vca_password": "secret",
-            "vca_cacert": "",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-        app_name = "mon"
-        port = 8000
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertIsNone(spec)
-
-    def test_make_pod_spec_without_config(self) -> NoReturn:
-        """Testing make pod spec without config."""
-        image_info = {"upstream-source": "opensourcemano/mon:8"}
-        config = {}
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-        app_name = "mon"
-        port = 8000
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-    def test_make_pod_spec_without_relation_state(self) -> NoReturn:
-        """Testing make pod spec without relation_state."""
-        image_info = {"upstream-source": "opensourcemano/mon:8"}
-        config = {
-            "site_url": "",
-            "openstack_default_granularity": 300,
-            "global_request_timeout": 10,
-            "log_level": "INFO",
-            "database_commonkey": "osm",
-            "collector_interval": 30,
-            "evaluator_interval": 30,
-            "vca_host": "admin",
-            "vca_user": "admin",
-            "vca_password": "secret",
-            "vca_cacert": "",
-        }
-        relation_state = {}
-        app_name = "mon"
-        port = 8000
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/mon/tox.ini b/installers/charm/mon/tox.ini
deleted file mode 100644 (file)
index f3c9144..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-#######################################################################################
-
-[tox]
-envlist = black, cover, flake8, pylint, yamllint, safety
-skipsdist = true
-
-[tox:jenkins]
-toxworkdir = /tmp/.tox
-
-[testenv]
-basepython = python3.8
-setenv =
-  VIRTUAL_ENV={envdir}
-  PYTHONPATH = {toxinidir}:{toxinidir}/lib:{toxinidir}/src
-  PYTHONDONTWRITEBYTECODE = 1
-deps =  -r{toxinidir}/requirements.txt
-
-
-#######################################################################################
-[testenv:black]
-deps = black
-commands =
-        black --check --diff src/ tests/
-
-
-#######################################################################################
-[testenv:cover]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        coverage
-        nose2
-commands =
-        sh -c 'rm -f nosetests.xml'
-        coverage erase
-        nose2 -C --coverage src
-        coverage report --omit='*tests*'
-        coverage html -d ./cover --omit='*tests*'
-        coverage xml -o coverage.xml --omit=*tests*
-whitelist_externals = sh
-
-
-#######################################################################################
-[testenv:flake8]
-deps =  flake8
-        flake8-import-order
-commands =
-        flake8 src/ tests/
-
-
-#######################################################################################
-[testenv:pylint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        pylint==2.10.2
-commands =
-    pylint -E src/ tests/
-
-
-#######################################################################################
-[testenv:safety]
-setenv =
-        LC_ALL=C.UTF-8
-        LANG=C.UTF-8
-deps =  {[testenv]deps}
-        safety
-commands =
-        - safety check --full-report
-
-
-#######################################################################################
-[testenv:yamllint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        yamllint
-commands = yamllint .
-
-#######################################################################################
-[testenv:build]
-passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
-whitelist_externals =
-  charmcraft
-  sh
-commands =
-  charmcraft pack
-  sh -c 'ubuntu_version=20.04; \
-        architectures="amd64-aarch64-arm64"; \
-        charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \
-        mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm'
-
-#######################################################################################
-[flake8]
-ignore =
-        W291,
-        W293,
-        W503,
-        E123,
-        E125,
-        E226,
-        E241,
-exclude =
-        .git,
-        __pycache__,
-        .tox,
-max-line-length = 120
-show-source = True
-builtins = _
-max-complexity = 10
-import-order-style = google
diff --git a/installers/charm/nbi/.gitignore b/installers/charm/nbi/.gitignore
deleted file mode 100644 (file)
index 2885df2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.stestr
-cover
-release
\ No newline at end of file
diff --git a/installers/charm/nbi/.jujuignore b/installers/charm/nbi/.jujuignore
deleted file mode 100644 (file)
index 3ae3e7d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.gitignore
-.stestr
-cover
-release
-tests/
-requirements*
-tox.ini
diff --git a/installers/charm/nbi/.yamllint.yaml b/installers/charm/nbi/.yamllint.yaml
deleted file mode 100644 (file)
index d71fb69..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
----
-extends: default
-
-yaml-files:
-  - "*.yaml"
-  - "*.yml"
-  - ".yamllint"
-ignore: |
-  .tox
-  cover/
-  build/
-  venv
-  release/
diff --git a/installers/charm/nbi/README.md b/installers/charm/nbi/README.md
deleted file mode 100644 (file)
index de0a4bf..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<!-- Copyright 2020 Canonical Ltd.
-
-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.
-
-For those usages not covered by the Apache License, Version 2.0 please
-contact: legal@canonical.com
-
-To get in touch with the maintainers, please contact:
-osm-charmers@lists.launchpad.net -->
-
-# NBI operator Charm for Kubernetes
-
-## Requirements
\ No newline at end of file
diff --git a/installers/charm/nbi/charmcraft.yaml b/installers/charm/nbi/charmcraft.yaml
deleted file mode 100644 (file)
index 0a285a9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-type: charm
-bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: ["amd64"]
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-          - aarch64
-          - arm64
-parts:
-  charm:
-    build-packages: [git]
diff --git a/installers/charm/nbi/config.yaml b/installers/charm/nbi/config.yaml
deleted file mode 100644 (file)
index f10304f..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-options:
-  max_file_size:
-    type: int
-    description: |
-      The maximum file size, in megabytes. If there is a reverse proxy in front
-      of Keystone, it may need to be configured to handle the requested size.
-      Note: if set to 0, there is no limit.
-    default: 0
-  ingress_class:
-    type: string
-    description: |
-      Ingress class name. This is useful for selecting the ingress to be used
-      in case there are multiple ingresses in the underlying k8s clusters.
-  ingress_whitelist_source_range:
-    type: string
-    description: |
-      A comma-separated list of CIDRs to store in the
-      ingress.kubernetes.io/whitelist-source-range annotation.
-
-      This can be used to lock down access to
-      Keystone based on source IP address.
-    default: ""
-  tls_secret_name:
-    type: string
-    description: TLS Secret name
-    default: ""
-  site_url:
-    type: string
-    description: Ingress URL
-    default: ""
-  cluster_issuer:
-    type: string
-    description: Name of the cluster issuer for TLS certificates
-    default: ""
-  log_level:
-    description: "Log Level"
-    type: string
-    default: "INFO"
-  database_commonkey:
-    description: Database COMMON KEY
-    type: string
-    default: osm
-  auth_backend:
-    type: string
-    description: Authentication backend ('internal' or 'keystone')
-    default: internal
-  enable_test:
-    type: boolean
-    description: Enable test endpoints of NBI.
-    default: false
-  mongodb_uri:
-    type: string
-    description: MongoDB URI (external database)
-  image_pull_policy:
-    type: string
-    description: |
-      ImagePullPolicy configuration for the pod.
-      Possible values: always, ifnotpresent, never
-    default: always
-  debug_mode:
-    description: |
-      If true, debug mode is activated. It means that the service will not run,
-      and instead, the command for the container will be a `sleep infinity`.
-      Note: If enabled, security_context will be disabled.
-    type: boolean
-    default: false
-  debug_pubkey:
-    description: |
-      Public SSH key that will be injected to the application pod.
-    type: string
-  debug_nbi_local_path:
-    description: |
-      Local full path to the NBI project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  debug_common_local_path:
-    description: |
-      Local full path to the COMMON project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  security_context:
-    description: Enables the security context of the pods
-    type: boolean
-    default: false
diff --git a/installers/charm/nbi/lib/charms/kafka_k8s/v0/kafka.py b/installers/charm/nbi/lib/charms/kafka_k8s/v0/kafka.py
deleted file mode 100644 (file)
index 1baf9a8..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2022 Canonical Ltd.
-# See LICENSE file for licensing details.
-#
-# 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.
-
-"""Kafka library.
-
-This [library](https://juju.is/docs/sdk/libraries) implements both sides of the
-`kafka` [interface](https://juju.is/docs/sdk/relations).
-
-The *provider* side of this interface is implemented by the
-[kafka-k8s Charmed Operator](https://charmhub.io/kafka-k8s).
-
-Any Charmed Operator that *requires* Kafka for providing its
-service should implement the *requirer* side of this interface.
-
-In a nutshell using this library to implement a Charmed Operator *requiring*
-Kafka would look like
-
-```
-$ charmcraft fetch-lib charms.kafka_k8s.v0.kafka
-```
-
-`metadata.yaml`:
-
-```
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-```
-
-`src/charm.py`:
-
-```
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.charm import CharmBase
-
-
-class MyCharm(CharmBase):
-
-    on = KafkaEvents()
-
-    def __init__(self, *args):
-        super().__init__(*args)
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(
-            self.on.kafka_available,
-            self._on_kafka_available,
-        )
-        self.framework.observe(
-            self.on.kafka_broken,
-            self._on_kafka_broken,
-        )
-
-    def _on_kafka_available(self, event):
-        # Get Kafka host and port
-        host: str = self.kafka.host
-        port: int = self.kafka.port
-        # host => "kafka-k8s"
-        # port => 9092
-
-    def _on_kafka_broken(self, event):
-        # Stop service
-        # ...
-        self.unit.status = BlockedStatus("need kafka relation")
-```
-
-You can file bugs
-[here](https://github.com/charmed-osm/kafka-k8s-operator/issues)!
-"""
-
-from typing import Optional
-
-from ops.charm import CharmBase, CharmEvents
-from ops.framework import EventBase, EventSource, Object
-
-# The unique Charmhub library identifier, never change it
-from ops.model import Relation
-
-LIBID = "eacc8c85082347c9aae740e0220b8376"
-
-# Increment this major API version when introducing breaking changes
-LIBAPI = 0
-
-# Increment this PATCH version before using `charmcraft publish-lib` or reset
-# to 0 if you are raising the major API version
-LIBPATCH = 3
-
-
-KAFKA_HOST_APP_KEY = "host"
-KAFKA_PORT_APP_KEY = "port"
-
-
-class _KafkaAvailableEvent(EventBase):
-    """Event emitted when Kafka is available."""
-
-
-class _KafkaBrokenEvent(EventBase):
-    """Event emitted when Kafka relation is broken."""
-
-
-class KafkaEvents(CharmEvents):
-    """Kafka events.
-
-    This class defines the events that Kafka can emit.
-
-    Events:
-        kafka_available (_KafkaAvailableEvent)
-    """
-
-    kafka_available = EventSource(_KafkaAvailableEvent)
-    kafka_broken = EventSource(_KafkaBrokenEvent)
-
-
-class KafkaRequires(Object):
-    """Requires-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self.charm = charm
-        self._endpoint_name = endpoint_name
-
-        # Observe relation events
-        event_observe_mapping = {
-            charm.on[self._endpoint_name].relation_changed: self._on_relation_changed,
-            charm.on[self._endpoint_name].relation_broken: self._on_relation_broken,
-        }
-        for event, observer in event_observe_mapping.items():
-            self.framework.observe(event, observer)
-
-    def _on_relation_changed(self, event) -> None:
-        if event.relation.app and all(
-            key in event.relation.data[event.relation.app]
-            for key in (KAFKA_HOST_APP_KEY, KAFKA_PORT_APP_KEY)
-        ):
-            self.charm.on.kafka_available.emit()
-
-    def _on_relation_broken(self, _) -> None:
-        self.charm.on.kafka_broken.emit()
-
-    @property
-    def host(self) -> str:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            relation.data[relation.app].get(KAFKA_HOST_APP_KEY)
-            if relation and relation.app
-            else None
-        )
-
-    @property
-    def port(self) -> int:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            int(relation.data[relation.app].get(KAFKA_PORT_APP_KEY))
-            if relation and relation.app
-            else None
-        )
-
-
-class KafkaProvides(Object):
-    """Provides-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self._endpoint_name = endpoint_name
-
-    def set_host_info(self, host: str, port: int, relation: Optional[Relation] = None) -> None:
-        """Set Kafka host and port.
-
-        This function writes in the application data of the relation, therefore,
-        only the unit leader can call it.
-
-        Args:
-            host (str): Kafka hostname or IP address.
-            port (int): Kafka port.
-            relation (Optional[Relation]): Relation to update.
-                                           If not specified, all relations will be updated.
-
-        Raises:
-            Exception: if a non-leader unit calls this function.
-        """
-        if not self.model.unit.is_leader():
-            raise Exception("only the leader set host information.")
-
-        if relation:
-            self._update_relation_data(host, port, relation)
-            return
-
-        for relation in self.model.relations[self._endpoint_name]:
-            self._update_relation_data(host, port, relation)
-
-    def _update_relation_data(self, host: str, port: int, relation: Relation) -> None:
-        """Update data in relation if needed."""
-        relation.data[self.model.app][KAFKA_HOST_APP_KEY] = host
-        relation.data[self.model.app][KAFKA_PORT_APP_KEY] = str(port)
diff --git a/installers/charm/nbi/metadata.yaml b/installers/charm/nbi/metadata.yaml
deleted file mode 100644 (file)
index 381497b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-name: osm-nbi
-summary: OSM Northbound Interface (NBI)
-description: |
-  A CAAS charm to deploy OSM's Northbound Interface (NBI).
-series:
-  - kubernetes
-tags:
-  - kubernetes
-  - osm
-  - nbi
-min-juju-version: 2.8.0
-deployment:
-  type: stateless
-  service: cluster
-resources:
-  image:
-    type: oci-image
-    description: OSM docker image for NBI
-    upstream-source: "opensourcemano/nbi:latest"
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-  mongodb:
-    interface: mongodb
-    limit: 1
-  keystone:
-    interface: keystone
-    limit: 1
-  prometheus:
-    interface: prometheus
-    limit: 1
-provides:
-  nbi:
-    interface: http
diff --git a/installers/charm/nbi/requirements-test.txt b/installers/charm/nbi/requirements-test.txt
deleted file mode 100644 (file)
index 316f6d2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-
-mock==4.0.3
diff --git a/installers/charm/nbi/requirements.txt b/installers/charm/nbi/requirements.txt
deleted file mode 100644 (file)
index 8bb93ad..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master
diff --git a/installers/charm/nbi/src/charm.py b/installers/charm/nbi/src/charm.py
deleted file mode 100755 (executable)
index cb47d1c..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213
-
-
-from ipaddress import ip_network
-import logging
-from typing import NoReturn, Optional
-from urllib.parse import urlparse
-
-
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.main import main
-from opslib.osm.charm import CharmedOsmBase, RelationsMissing
-from opslib.osm.interfaces.http import HttpServer
-from opslib.osm.interfaces.keystone import KeystoneClient
-from opslib.osm.interfaces.mongo import MongoClient
-from opslib.osm.interfaces.prometheus import PrometheusClient
-from opslib.osm.pod import (
-    ContainerV3Builder,
-    IngressResourceV3Builder,
-    PodRestartPolicy,
-    PodSpecV3Builder,
-)
-from opslib.osm.validator import ModelValidator, validator
-
-
-logger = logging.getLogger(__name__)
-
-PORT = 9999
-
-
-class ConfigModel(ModelValidator):
-    enable_test: bool
-    auth_backend: str
-    database_commonkey: str
-    log_level: str
-    max_file_size: int
-    site_url: Optional[str]
-    cluster_issuer: Optional[str]
-    ingress_class: Optional[str]
-    ingress_whitelist_source_range: Optional[str]
-    tls_secret_name: Optional[str]
-    mongodb_uri: Optional[str]
-    image_pull_policy: str
-    debug_mode: bool
-    security_context: bool
-
-    @validator("auth_backend")
-    def validate_auth_backend(cls, v):
-        if v not in {"internal", "keystone"}:
-            raise ValueError("value must be 'internal' or 'keystone'")
-        return v
-
-    @validator("log_level")
-    def validate_log_level(cls, v):
-        if v not in {"INFO", "DEBUG"}:
-            raise ValueError("value must be INFO or DEBUG")
-        return v
-
-    @validator("max_file_size")
-    def validate_max_file_size(cls, v):
-        if v < 0:
-            raise ValueError("value must be equal or greater than 0")
-        return v
-
-    @validator("site_url")
-    def validate_site_url(cls, v):
-        if v:
-            parsed = urlparse(v)
-            if not parsed.scheme.startswith("http"):
-                raise ValueError("value must start with http")
-        return v
-
-    @validator("ingress_whitelist_source_range")
-    def validate_ingress_whitelist_source_range(cls, v):
-        if v:
-            ip_network(v)
-        return v
-
-    @validator("mongodb_uri")
-    def validate_mongodb_uri(cls, v):
-        if v and not v.startswith("mongodb://"):
-            raise ValueError("mongodb_uri is not properly formed")
-        return v
-
-    @validator("image_pull_policy")
-    def validate_image_pull_policy(cls, v):
-        values = {
-            "always": "Always",
-            "ifnotpresent": "IfNotPresent",
-            "never": "Never",
-        }
-        v = v.lower()
-        if v not in values.keys():
-            raise ValueError("value must be always, ifnotpresent or never")
-        return values[v]
-
-
-class NbiCharm(CharmedOsmBase):
-    on = KafkaEvents()
-
-    def __init__(self, *args) -> NoReturn:
-        super().__init__(
-            *args,
-            oci_image="image",
-            vscode_workspace=VSCODE_WORKSPACE,
-        )
-        if self.config.get("debug_mode"):
-            self.enable_debug_mode(
-                pubkey=self.config.get("debug_pubkey"),
-                hostpaths={
-                    "NBI": {
-                        "hostpath": self.config.get("debug_nbi_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_nbi",
-                    },
-                    "osm_common": {
-                        "hostpath": self.config.get("debug_common_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_common",
-                    },
-                },
-            )
-
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(self.on.kafka_available, self.configure_pod)
-        self.framework.observe(self.on.kafka_broken, self.configure_pod)
-
-        self.mongodb_client = MongoClient(self, "mongodb")
-        self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
-
-        self.prometheus_client = PrometheusClient(self, "prometheus")
-        self.framework.observe(
-            self.on["prometheus"].relation_changed, self.configure_pod
-        )
-        self.framework.observe(
-            self.on["prometheus"].relation_broken, self.configure_pod
-        )
-
-        self.keystone_client = KeystoneClient(self, "keystone")
-        self.framework.observe(self.on["keystone"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["keystone"].relation_broken, self.configure_pod)
-
-        self.http_server = HttpServer(self, "nbi")
-        self.framework.observe(self.on["nbi"].relation_joined, self._publish_nbi_info)
-
-    def _publish_nbi_info(self, event):
-        """Publishes NBI information.
-
-        Args:
-            event (EventBase): RO relation event.
-        """
-        if self.unit.is_leader():
-            self.http_server.publish_info(self.app.name, PORT)
-
-    def _check_missing_dependencies(self, config: ConfigModel):
-        missing_relations = []
-
-        if not self.kafka.host or not self.kafka.port:
-            missing_relations.append("kafka")
-        if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
-            missing_relations.append("mongodb")
-        if self.prometheus_client.is_missing_data_in_app():
-            missing_relations.append("prometheus")
-        if config.auth_backend == "keystone":
-            if self.keystone_client.is_missing_data_in_app():
-                missing_relations.append("keystone")
-
-        if missing_relations:
-            raise RelationsMissing(missing_relations)
-
-    def build_pod_spec(self, image_info):
-        # Validate config
-        config = ConfigModel(**dict(self.config))
-
-        if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
-            raise Exception("Mongodb data cannot be provided via config and relation")
-
-        # Check relations
-        self._check_missing_dependencies(config)
-
-        security_context_enabled = (
-            config.security_context if not config.debug_mode else False
-        )
-
-        # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder(
-            enable_security_context=security_context_enabled
-        )
-
-        # Add secrets to the pod
-        mongodb_secret_name = f"{self.app.name}-mongodb-secret"
-        pod_spec_builder.add_secret(
-            mongodb_secret_name,
-            {
-                "uri": config.mongodb_uri or self.mongodb_client.connection_string,
-                "commonkey": config.database_commonkey,
-            },
-        )
-
-        # Build Init Container
-        pod_spec_builder.add_init_container(
-            {
-                "name": "init-check",
-                "image": "alpine:latest",
-                "command": [
-                    "sh",
-                    "-c",
-                    f"until (nc -zvw1 {self.kafka.host} {self.kafka.port} ); do sleep 3; done; exit 0",
-                ],
-            }
-        )
-
-        # Build Container
-        container_builder = ContainerV3Builder(
-            self.app.name,
-            image_info,
-            config.image_pull_policy,
-            run_as_non_root=security_context_enabled,
-        )
-        container_builder.add_port(name=self.app.name, port=PORT)
-        container_builder.add_tcpsocket_readiness_probe(
-            PORT,
-            initial_delay_seconds=5,
-            timeout_seconds=5,
-        )
-        container_builder.add_tcpsocket_liveness_probe(
-            PORT,
-            initial_delay_seconds=45,
-            timeout_seconds=10,
-        )
-        container_builder.add_envs(
-            {
-                # General configuration
-                "ALLOW_ANONYMOUS_LOGIN": "yes",
-                "OSMNBI_SERVER_ENABLE_TEST": config.enable_test,
-                "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
-                # Kafka configuration
-                "OSMNBI_MESSAGE_HOST": self.kafka.host,
-                "OSMNBI_MESSAGE_DRIVER": "kafka",
-                "OSMNBI_MESSAGE_PORT": self.kafka.port,
-                # Database configuration
-                "OSMNBI_DATABASE_DRIVER": "mongo",
-                # Storage configuration
-                "OSMNBI_STORAGE_DRIVER": "mongo",
-                "OSMNBI_STORAGE_PATH": "/app/storage",
-                "OSMNBI_STORAGE_COLLECTION": "files",
-                # Prometheus configuration
-                "OSMNBI_PROMETHEUS_HOST": self.prometheus_client.hostname,
-                "OSMNBI_PROMETHEUS_PORT": self.prometheus_client.port,
-                # Log configuration
-                "OSMNBI_LOG_LEVEL": config.log_level,
-            }
-        )
-        container_builder.add_secret_envs(
-            secret_name=mongodb_secret_name,
-            envs={
-                "OSMNBI_DATABASE_URI": "uri",
-                "OSMNBI_DATABASE_COMMONKEY": "commonkey",
-                "OSMNBI_STORAGE_URI": "uri",
-            },
-        )
-        if config.auth_backend == "internal":
-            container_builder.add_env("OSMNBI_AUTHENTICATION_BACKEND", "internal")
-        elif config.auth_backend == "keystone":
-            keystone_secret_name = f"{self.app.name}-keystone-secret"
-            pod_spec_builder.add_secret(
-                keystone_secret_name,
-                {
-                    "url": self.keystone_client.host,
-                    "port": self.keystone_client.port,
-                    "user_domain": self.keystone_client.user_domain_name,
-                    "project_domain": self.keystone_client.project_domain_name,
-                    "service_username": self.keystone_client.username,
-                    "service_password": self.keystone_client.password,
-                    "service_project": self.keystone_client.service,
-                },
-            )
-            container_builder.add_env("OSMNBI_AUTHENTICATION_BACKEND", "keystone")
-            container_builder.add_secret_envs(
-                secret_name=keystone_secret_name,
-                envs={
-                    "OSMNBI_AUTHENTICATION_AUTH_URL": "url",
-                    "OSMNBI_AUTHENTICATION_AUTH_PORT": "port",
-                    "OSMNBI_AUTHENTICATION_USER_DOMAIN_NAME": "user_domain",
-                    "OSMNBI_AUTHENTICATION_PROJECT_DOMAIN_NAME": "project_domain",
-                    "OSMNBI_AUTHENTICATION_SERVICE_USERNAME": "service_username",
-                    "OSMNBI_AUTHENTICATION_SERVICE_PASSWORD": "service_password",
-                    "OSMNBI_AUTHENTICATION_SERVICE_PROJECT": "service_project",
-                },
-            )
-        container = container_builder.build()
-
-        # Add container to pod spec
-        pod_spec_builder.add_container(container)
-
-        # Add ingress resources to pod spec if site url exists
-        if config.site_url:
-            parsed = urlparse(config.site_url)
-            annotations = {
-                "nginx.ingress.kubernetes.io/proxy-body-size": "{}".format(
-                    str(config.max_file_size) + "m"
-                    if config.max_file_size > 0
-                    else config.max_file_size
-                ),
-                "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
-            }
-            if config.ingress_class:
-                annotations["kubernetes.io/ingress.class"] = config.ingress_class
-            ingress_resource_builder = IngressResourceV3Builder(
-                f"{self.app.name}-ingress", annotations
-            )
-
-            if config.ingress_whitelist_source_range:
-                annotations[
-                    "nginx.ingress.kubernetes.io/whitelist-source-range"
-                ] = config.ingress_whitelist_source_range
-
-            if config.cluster_issuer:
-                annotations["cert-manager.io/cluster-issuer"] = config.cluster_issuer
-
-            if parsed.scheme == "https":
-                ingress_resource_builder.add_tls(
-                    [parsed.hostname], config.tls_secret_name
-                )
-            else:
-                annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
-
-            ingress_resource_builder.add_rule(parsed.hostname, self.app.name, PORT)
-            ingress_resource = ingress_resource_builder.build()
-            pod_spec_builder.add_ingress_resource(ingress_resource)
-
-        # Add restart policy
-        restart_policy = PodRestartPolicy()
-        restart_policy.add_secrets()
-        pod_spec_builder.set_restart_policy(restart_policy)
-
-        return pod_spec_builder.build()
-
-
-VSCODE_WORKSPACE = {
-    "folders": [
-        {"path": "/usr/lib/python3/dist-packages/osm_nbi"},
-        {"path": "/usr/lib/python3/dist-packages/osm_common"},
-        {"path": "/usr/lib/python3/dist-packages/osm_im"},
-    ],
-    "settings": {},
-    "launch": {
-        "version": "0.2.0",
-        "configurations": [
-            {
-                "name": "NBI",
-                "type": "python",
-                "request": "launch",
-                "module": "osm_nbi.nbi",
-                "justMyCode": False,
-            }
-        ],
-    },
-}
-
-
-if __name__ == "__main__":
-    main(NbiCharm)
diff --git a/installers/charm/nbi/src/pod_spec.py b/installers/charm/nbi/src/pod_spec.py
deleted file mode 100644 (file)
index b8f5904..0000000
+++ /dev/null
@@ -1,419 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-from ipaddress import ip_network
-from typing import Any, Callable, Dict, List, NoReturn
-from urllib.parse import urlparse
-
-
-def _validate_max_file_size(max_file_size: int, site_url: str) -> bool:
-    """Validate max_file_size.
-
-    Args:
-        max_file_size (int): maximum file size allowed.
-        site_url (str): endpoint url.
-
-    Returns:
-        bool: True if valid, false otherwise.
-    """
-    if not site_url:
-        return True
-
-    parsed = urlparse(site_url)
-
-    if not parsed.scheme.startswith("http"):
-        return True
-
-    if max_file_size is None:
-        return False
-
-    return max_file_size >= 0
-
-
-def _validate_ip_network(network: str) -> bool:
-    """Validate IP network.
-
-    Args:
-        network (str): IP network range.
-
-    Returns:
-        bool: True if valid, false otherwise.
-    """
-    if not network:
-        return True
-
-    try:
-        ip_network(network)
-    except ValueError:
-        return False
-
-    return True
-
-
-def _validate_keystone_config(keystone: bool, value: Any, validator: Callable) -> bool:
-    """Validate keystone configurations.
-
-    Args:
-        keystone (bool): is keystone enabled, true if so, false otherwise.
-        value (Any): value to be validated.
-        validator (Callable): function to validate configuration.
-
-    Returns:
-        bool: true if valid, false otherwise.
-    """
-    if not keystone:
-        return True
-
-    return validator(value)
-
-
-def _validate_data(
-    config_data: Dict[str, Any], relation_data: Dict[str, Any], keystone: bool
-) -> NoReturn:
-    """Validate input data.
-
-    Args:
-        config_data (Dict[str, Any]): configuration data.
-        relation_data (Dict[str, Any]): relation data.
-        keystone (bool): is keystone to be used.
-    """
-    config_validators = {
-        "enable_test": lambda value, _: isinstance(value, bool),
-        "database_commonkey": lambda value, _: (
-            isinstance(value, str) and len(value) > 1
-        ),
-        "log_level": lambda value, _: (
-            isinstance(value, str) and value in ("INFO", "DEBUG")
-        ),
-        "auth_backend": lambda value, _: (
-            isinstance(value, str) and (value == "internal" or value == "keystone")
-        ),
-        "site_url": lambda value, _: isinstance(value, str)
-        if value is not None
-        else True,
-        "max_file_size": lambda value, values: _validate_max_file_size(
-            value, values.get("site_url")
-        ),
-        "ingress_whitelist_source_range": lambda value, _: _validate_ip_network(value),
-        "tls_secret_name": lambda value, _: isinstance(value, str)
-        if value is not None
-        else True,
-    }
-    relation_validators = {
-        "message_host": lambda value, _: isinstance(value, str),
-        "message_port": lambda value, _: isinstance(value, int) and value > 0,
-        "database_uri": lambda value, _: (
-            isinstance(value, str) and value.startswith("mongodb://")
-        ),
-        "prometheus_host": lambda value, _: isinstance(value, str),
-        "prometheus_port": lambda value, _: isinstance(value, int) and value > 0,
-        "keystone_host": lambda value, _: _validate_keystone_config(
-            keystone, value, lambda x: isinstance(x, str) and len(x) > 0
-        ),
-        "keystone_port": lambda value, _: _validate_keystone_config(
-            keystone, value, lambda x: isinstance(x, int) and x > 0
-        ),
-        "keystone_user_domain_name": lambda value, _: _validate_keystone_config(
-            keystone, value, lambda x: isinstance(x, str) and len(x) > 0
-        ),
-        "keystone_project_domain_name": lambda value, _: _validate_keystone_config(
-            keystone, value, lambda x: isinstance(x, str) and len(x) > 0
-        ),
-        "keystone_username": lambda value, _: _validate_keystone_config(
-            keystone, value, lambda x: isinstance(x, str) and len(x) > 0
-        ),
-        "keystone_password": lambda value, _: _validate_keystone_config(
-            keystone, value, lambda x: isinstance(x, str) and len(x) > 0
-        ),
-        "keystone_service": lambda value, _: _validate_keystone_config(
-            keystone, value, lambda x: isinstance(x, str) and len(x) > 0
-        ),
-    }
-    problems = []
-
-    for key, validator in config_validators.items():
-        valid = validator(config_data.get(key), config_data)
-
-        if not valid:
-            problems.append(key)
-
-    for key, validator in relation_validators.items():
-        valid = validator(relation_data.get(key), relation_data)
-
-        if not valid:
-            problems.append(key)
-
-    if len(problems) > 0:
-        raise ValueError("Errors found in: {}".format(", ".join(problems)))
-
-
-def _make_pod_ports(port: int) -> List[Dict[str, Any]]:
-    """Generate pod ports details.
-
-    Args:
-        port (int): port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod port details.
-    """
-    return [{"name": "nbi", "containerPort": port, "protocol": "TCP"}]
-
-
-def _make_pod_envconfig(
-    config: Dict[str, Any], relation_state: Dict[str, Any]
-) -> Dict[str, Any]:
-    """Generate pod environment configuration.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-        relation_state (Dict[str, Any]): relation state information.
-
-    Returns:
-        Dict[str, Any]: pod environment configuration.
-    """
-    envconfig = {
-        # General configuration
-        "ALLOW_ANONYMOUS_LOGIN": "yes",
-        "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
-        "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
-        # Kafka configuration
-        "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
-        "OSMNBI_MESSAGE_DRIVER": "kafka",
-        "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
-        # Database configuration
-        "OSMNBI_DATABASE_DRIVER": "mongo",
-        "OSMNBI_DATABASE_URI": relation_state["database_uri"],
-        "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
-        # Storage configuration
-        "OSMNBI_STORAGE_DRIVER": "mongo",
-        "OSMNBI_STORAGE_PATH": "/app/storage",
-        "OSMNBI_STORAGE_COLLECTION": "files",
-        "OSMNBI_STORAGE_URI": relation_state["database_uri"],
-        # Prometheus configuration
-        "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
-        "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
-        # Log configuration
-        "OSMNBI_LOG_LEVEL": config["log_level"],
-    }
-
-    if config["auth_backend"] == "internal":
-        envconfig["OSMNBI_AUTHENTICATION_BACKEND"] = "internal"
-    elif config["auth_backend"] == "keystone":
-        envconfig.update(
-            {
-                "OSMNBI_AUTHENTICATION_BACKEND": "keystone",
-                "OSMNBI_AUTHENTICATION_AUTH_URL": relation_state["keystone_host"],
-                "OSMNBI_AUTHENTICATION_AUTH_PORT": relation_state["keystone_port"],
-                "OSMNBI_AUTHENTICATION_USER_DOMAIN_NAME": relation_state[
-                    "keystone_user_domain_name"
-                ],
-                "OSMNBI_AUTHENTICATION_PROJECT_DOMAIN_NAME": relation_state[
-                    "keystone_project_domain_name"
-                ],
-                "OSMNBI_AUTHENTICATION_SERVICE_USERNAME": relation_state[
-                    "keystone_username"
-                ],
-                "OSMNBI_AUTHENTICATION_SERVICE_PASSWORD": relation_state[
-                    "keystone_password"
-                ],
-                "OSMNBI_AUTHENTICATION_SERVICE_PROJECT": relation_state[
-                    "keystone_service"
-                ],
-            }
-        )
-    else:
-        raise ValueError("auth_backend needs to be either internal or keystone")
-
-    return envconfig
-
-
-def _make_pod_ingress_resources(
-    config: Dict[str, Any], app_name: str, port: int
-) -> List[Dict[str, Any]]:
-    """Generate pod ingress resources.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-        app_name (str): application name.
-        port (int): port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod ingress resources.
-    """
-    site_url = config.get("site_url")
-
-    if not site_url:
-        return
-
-    parsed = urlparse(site_url)
-
-    if not parsed.scheme.startswith("http"):
-        return
-
-    max_file_size = config["max_file_size"]
-    ingress_whitelist_source_range = config["ingress_whitelist_source_range"]
-
-    annotations = {
-        "nginx.ingress.kubernetes.io/proxy-body-size": "{}".format(
-            str(max_file_size) + "m" if max_file_size > 0 else max_file_size
-        ),
-        "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
-    }
-
-    if ingress_whitelist_source_range:
-        annotations[
-            "nginx.ingress.kubernetes.io/whitelist-source-range"
-        ] = ingress_whitelist_source_range
-
-    ingress_spec_tls = None
-
-    if parsed.scheme == "https":
-        ingress_spec_tls = [{"hosts": [parsed.hostname]}]
-        tls_secret_name = config["tls_secret_name"]
-        if tls_secret_name:
-            ingress_spec_tls[0]["secretName"] = tls_secret_name
-    else:
-        annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
-
-    ingress = {
-        "name": "{}-ingress".format(app_name),
-        "annotations": annotations,
-        "spec": {
-            "rules": [
-                {
-                    "host": parsed.hostname,
-                    "http": {
-                        "paths": [
-                            {
-                                "path": "/",
-                                "backend": {
-                                    "serviceName": app_name,
-                                    "servicePort": port,
-                                },
-                            }
-                        ]
-                    },
-                }
-            ]
-        },
-    }
-    if ingress_spec_tls:
-        ingress["spec"]["tls"] = ingress_spec_tls
-
-    return [ingress]
-
-
-def _make_startup_probe() -> Dict[str, Any]:
-    """Generate startup probe.
-
-    Returns:
-        Dict[str, Any]: startup probe.
-    """
-    return {
-        "exec": {"command": ["/usr/bin/pgrep python3"]},
-        "initialDelaySeconds": 60,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_readiness_probe(port: int) -> Dict[str, Any]:
-    """Generate readiness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: readiness probe.
-    """
-    return {
-        "httpGet": {
-            "path": "/osm/",
-            "port": port,
-        },
-        "initialDelaySeconds": 45,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_liveness_probe(port: int) -> Dict[str, Any]:
-    """Generate liveness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: liveness probe.
-    """
-    return {
-        "httpGet": {
-            "path": "/osm/",
-            "port": port,
-        },
-        "initialDelaySeconds": 45,
-        "timeoutSeconds": 5,
-    }
-
-
-def make_pod_spec(
-    image_info: Dict[str, str],
-    config: Dict[str, Any],
-    relation_state: Dict[str, Any],
-    app_name: str = "nbi",
-    port: int = 9999,
-) -> Dict[str, Any]:
-    """Generate the pod spec information.
-
-    Args:
-        image_info (Dict[str, str]): Object provided by
-                                     OCIImageResource("image").fetch().
-        config (Dict[str, Any]): Configuration information.
-        relation_state (Dict[str, Any]): Relation state information.
-        app_name (str, optional): Application name. Defaults to "nbi".
-        port (int, optional): Port for the container. Defaults to 9999.
-
-    Returns:
-        Dict[str, Any]: Pod spec dictionary for the charm.
-    """
-    if not image_info:
-        return None
-
-    _validate_data(config, relation_state, config.get("auth_backend") == "keystone")
-
-    ports = _make_pod_ports(port)
-    env_config = _make_pod_envconfig(config, relation_state)
-    ingress_resources = _make_pod_ingress_resources(config, app_name, port)
-
-    return {
-        "version": 3,
-        "containers": [
-            {
-                "name": app_name,
-                "imageDetails": image_info,
-                "imagePullPolicy": "Always",
-                "ports": ports,
-                "envConfig": env_config,
-            }
-        ],
-        "kubernetesResources": {
-            "ingressResources": ingress_resources or [],
-        },
-    }
diff --git a/installers/charm/nbi/tests/__init__.py b/installers/charm/nbi/tests/__init__.py
deleted file mode 100644 (file)
index 446d5ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-"""Init mocking for unit tests."""
-
-import sys
-
-
-import mock
-
-
-class OCIImageResourceErrorMock(Exception):
-    pass
-
-
-sys.path.append("src")
-
-oci_image = mock.MagicMock()
-oci_image.OCIImageResourceError = OCIImageResourceErrorMock
-sys.modules["oci_image"] = oci_image
-sys.modules["oci_image"].OCIImageResource().fetch.return_value = {}
diff --git a/installers/charm/nbi/tests/test_charm.py b/installers/charm/nbi/tests/test_charm.py
deleted file mode 100644 (file)
index 92c2980..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import sys
-from typing import NoReturn
-import unittest
-
-
-from charm import NbiCharm
-from ops.model import ActiveStatus, BlockedStatus
-from ops.testing import Harness
-
-
-class TestCharm(unittest.TestCase):
-    """Prometheus Charm unit tests."""
-
-    def setUp(self) -> NoReturn:
-        """Test setup"""
-        self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
-        self.harness = Harness(NbiCharm)
-        self.harness.set_leader(is_leader=True)
-        self.harness.begin()
-        self.config = {
-            "enable_test": False,
-            "auth_backend": "internal",
-            "database_commonkey": "key",
-            "mongodb_uri": "",
-            "log_level": "INFO",
-            "max_file_size": 0,
-            "ingress_whitelist_source_range": "",
-            "tls_secret_name": "",
-            "site_url": "https://nbi.192.168.100.100.nip.io",
-            "cluster_issuer": "vault-issuer",
-        }
-        self.harness.update_config(self.config)
-
-    def test_config_changed_no_relations(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["mongodb", "kafka", "prometheus"]
-            )
-        )
-
-    def test_config_changed_non_leader(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-        self.harness.set_leader(is_leader=False)
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-    def test_with_relations_internal_and_mongodb_config(
-        self,
-    ) -> NoReturn:
-        "Test with relations and mongodb config (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_config()
-        self.initialize_prometheus_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations_internal(
-        self,
-    ) -> NoReturn:
-        "Test with relations (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_prometheus_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations_and_mongodb_config_with_keystone_missing(
-        self,
-    ) -> NoReturn:
-        "Test with relations and mongodb config (keystone)"
-        self.harness.update_config({"auth_backend": "keystone"})
-        self.initialize_kafka_relation()
-        self.initialize_mongo_config()
-        self.initialize_prometheus_relation()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue("keystone" in self.harness.charm.unit.status.message)
-
-    def test_with_relations_keystone_missing(
-        self,
-    ) -> NoReturn:
-        "Test with relations (keystone)"
-        self.harness.update_config({"auth_backend": "keystone"})
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_prometheus_relation()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue("keystone" in self.harness.charm.unit.status.message)
-
-    def test_with_relations_and_mongodb_config_with_keystone(
-        self,
-    ) -> NoReturn:
-        "Test with relations (keystone)"
-        self.harness.update_config({"auth_backend": "keystone"})
-        self.initialize_kafka_relation()
-        self.initialize_mongo_config()
-        self.initialize_prometheus_relation()
-        self.initialize_keystone_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations_keystone(
-        self,
-    ) -> NoReturn:
-        "Test with relations (keystone)"
-        self.harness.update_config({"auth_backend": "keystone"})
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_prometheus_relation()
-        self.initialize_keystone_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_mongodb_exception_relation_and_config(
-        self,
-    ) -> NoReturn:
-        self.initialize_mongo_config()
-        self.initialize_mongo_relation()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def initialize_kafka_relation(self):
-        kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-        self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-        self.harness.update_relation_data(
-            kafka_relation_id, "kafka", {"host": "kafka", "port": 9092}
-        )
-
-    def initialize_mongo_config(self):
-        self.harness.update_config({"mongodb_uri": "mongodb://mongo:27017"})
-
-    def initialize_mongo_relation(self):
-        mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-        self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mongodb/0",
-            {"connection_string": "mongodb://mongo:27017"},
-        )
-
-    def initialize_keystone_relation(self):
-        keystone_relation_id = self.harness.add_relation("keystone", "keystone")
-        self.harness.add_relation_unit(keystone_relation_id, "keystone/0")
-        self.harness.update_relation_data(
-            keystone_relation_id,
-            "keystone",
-            {
-                "host": "host",
-                "port": 5000,
-                "user_domain_name": "ud",
-                "project_domain_name": "pd",
-                "username": "u",
-                "password": "p",
-                "service": "s",
-                "keystone_db_password": "something",
-                "region_id": "something",
-                "admin_username": "something",
-                "admin_password": "something",
-                "admin_project_name": "something",
-            },
-        )
-
-    def initialize_prometheus_relation(self):
-        prometheus_relation_id = self.harness.add_relation("prometheus", "prometheus")
-        self.harness.add_relation_unit(prometheus_relation_id, "prometheus/0")
-        self.harness.update_relation_data(
-            prometheus_relation_id,
-            "prometheus",
-            {"hostname": "prometheus", "port": 9090},
-        )
-
-
-if __name__ == "__main__":
-    unittest.main()
-
-
-# class TestCharm(unittest.TestCase):
-#     """Prometheus Charm unit tests."""
-
-#     def setUp(self) -> NoReturn:
-#         """Test setup"""
-#         self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
-#         self.harness = Harness(NbiCharm)
-#         self.harness.set_leader(is_leader=True)
-#         self.harness.begin()
-#         self.config = {
-#             "enable_ng_ro": True,
-#             "database_commonkey": "commonkey",
-#             "log_level": "INFO",
-#             "vim_database": "db_name",
-#             "ro_database": "ro_db_name",
-#             "openmano_tenant": "mano",
-#         }
-
-#     def test_config_changed_no_relations(
-#         self,
-#     ) -> NoReturn:
-#         """Test ingress resources without HTTP."""
-
-#         self.harness.charm.on.config_changed.emit()
-
-#         # Assertions
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-#         self.assertTrue(
-#             all(
-#                 relation in self.harness.charm.unit.status.message
-#                 for relation in ["mongodb", "kafka"]
-#             )
-#         )
-
-#         # Disable ng-ro
-#         self.harness.update_config({"enable_ng_ro": False})
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-#         self.assertTrue(
-#             all(
-#                 relation in self.harness.charm.unit.status.message
-#                 for relation in ["mysql"]
-#             )
-#         )
-
-#     def test_config_changed_non_leader(
-#         self,
-#     ) -> NoReturn:
-#         """Test ingress resources without HTTP."""
-#         self.harness.set_leader(is_leader=False)
-#         self.harness.charm.on.config_changed.emit()
-
-#         # Assertions
-#         self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-#     def test_with_relations_ng(
-#         self,
-#     ) -> NoReturn:
-#         "Test with relations (ng-ro)"
-
-#         # Initializing the kafka relation
-#         kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             kafka_relation_id, "kafka/0", {"host": "kafka", "port": 9092}
-#         )
-
-#         # Initializing the mongo relation
-#         mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             mongodb_relation_id,
-#             "mongodb/0",
-#             {"connection_string": "mongodb://mongo:27017"},
-#         )
-
-#         self.harness.charm.on.config_changed.emit()
-
-#         # Verifying status
-#         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-
-# if __name__ == "__main__":
-#     unittest.main()
diff --git a/installers/charm/nbi/tests/test_pod_spec.py b/installers/charm/nbi/tests/test_pod_spec.py
deleted file mode 100644 (file)
index 360895f..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-from typing import NoReturn
-import unittest
-
-import pod_spec
-
-
-class TestPodSpec(unittest.TestCase):
-    """Pod spec unit tests."""
-
-    def test_make_pod_ports(self) -> NoReturn:
-        """Testing make pod ports."""
-        port = 9999
-
-        expected_result = [
-            {
-                "name": "nbi",
-                "containerPort": port,
-                "protocol": "TCP",
-            }
-        ]
-
-        pod_ports = pod_spec._make_pod_ports(port)
-
-        self.assertListEqual(expected_result, pod_ports)
-
-    def test_make_pod_envconfig_without_keystone(self) -> NoReturn:
-        """Teting make pod envconfig without Keystone."""
-        config = {
-            "enable_test": False,
-            "database_commonkey": "commonkey",
-            "log_level": "DEBUG",
-            "auth_backend": "internal",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-
-        expected_result = {
-            "ALLOW_ANONYMOUS_LOGIN": "yes",
-            "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
-            "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
-            "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
-            "OSMNBI_MESSAGE_DRIVER": "kafka",
-            "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
-            "OSMNBI_DATABASE_DRIVER": "mongo",
-            "OSMNBI_DATABASE_URI": relation_state["database_uri"],
-            "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
-            "OSMNBI_STORAGE_DRIVER": "mongo",
-            "OSMNBI_STORAGE_PATH": "/app/storage",
-            "OSMNBI_STORAGE_COLLECTION": "files",
-            "OSMNBI_STORAGE_URI": relation_state["database_uri"],
-            "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
-            "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
-            "OSMNBI_LOG_LEVEL": config["log_level"],
-            "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_pod_envconfig_with_keystone(self) -> NoReturn:
-        """Teting make pod envconfig with Keystone."""
-        config = {
-            "enable_test": False,
-            "database_commonkey": "commonkey",
-            "log_level": "DEBUG",
-            "auth_backend": "keystone",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-            "keystone_host": "keystone",
-            "keystone_port": 5000,
-            "keystone_user_domain_name": "user_domain",
-            "keystone_project_domain_name": "project_domain",
-            "keystone_username": "username",
-            "keystone_password": "password",
-            "keystone_service": "service",
-        }
-
-        expected_result = {
-            "ALLOW_ANONYMOUS_LOGIN": "yes",
-            "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
-            "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
-            "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
-            "OSMNBI_MESSAGE_DRIVER": "kafka",
-            "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
-            "OSMNBI_DATABASE_DRIVER": "mongo",
-            "OSMNBI_DATABASE_URI": relation_state["database_uri"],
-            "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
-            "OSMNBI_STORAGE_DRIVER": "mongo",
-            "OSMNBI_STORAGE_PATH": "/app/storage",
-            "OSMNBI_STORAGE_COLLECTION": "files",
-            "OSMNBI_STORAGE_URI": relation_state["database_uri"],
-            "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
-            "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
-            "OSMNBI_LOG_LEVEL": config["log_level"],
-            "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
-            "OSMNBI_AUTHENTICATION_AUTH_URL": relation_state["keystone_host"],
-            "OSMNBI_AUTHENTICATION_AUTH_PORT": relation_state["keystone_port"],
-            "OSMNBI_AUTHENTICATION_USER_DOMAIN_NAME": relation_state[
-                "keystone_user_domain_name"
-            ],
-            "OSMNBI_AUTHENTICATION_PROJECT_DOMAIN_NAME": relation_state[
-                "keystone_project_domain_name"
-            ],
-            "OSMNBI_AUTHENTICATION_SERVICE_USERNAME": relation_state[
-                "keystone_username"
-            ],
-            "OSMNBI_AUTHENTICATION_SERVICE_PASSWORD": relation_state[
-                "keystone_password"
-            ],
-            "OSMNBI_AUTHENTICATION_SERVICE_PROJECT": relation_state["keystone_service"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_pod_envconfig_wrong_auth_backend(self) -> NoReturn:
-        """Teting make pod envconfig with wrong auth_backend."""
-        config = {
-            "enable_test": False,
-            "database_commonkey": "commonkey",
-            "log_level": "DEBUG",
-            "auth_backend": "kerberos",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-            "keystone_host": "keystone",
-            "keystone_port": 5000,
-            "keystone_user_domain_name": "user_domain",
-            "keystone_project_domain_name": "project_domain",
-            "keystone_username": "username",
-            "keystone_password": "password",
-            "keystone_service": "service",
-        }
-
-        with self.assertRaises(ValueError) as exc:
-            pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertTrue(
-            "auth_backend needs to be either internal or keystone" in str(exc.exception)
-        )
-
-    def test_make_pod_ingress_resources_without_site_url(self) -> NoReturn:
-        """Testing make pod ingress resources without site_url."""
-        config = {"site_url": ""}
-        app_name = "nbi"
-        port = 9999
-
-        pod_ingress_resources = pod_spec._make_pod_ingress_resources(
-            config, app_name, port
-        )
-
-        self.assertIsNone(pod_ingress_resources)
-
-    def test_make_pod_ingress_resources(self) -> NoReturn:
-        """Testing make pod ingress resources."""
-        config = {
-            "site_url": "http://nbi",
-            "max_file_size": 0,
-            "ingress_whitelist_source_range": "",
-        }
-        app_name = "nbi"
-        port = 9999
-
-        expected_result = [
-            {
-                "name": f"{app_name}-ingress",
-                "annotations": {
-                    "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
-                    "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
-                    "nginx.ingress.kubernetes.io/ssl-redirect": "false",
-                },
-                "spec": {
-                    "rules": [
-                        {
-                            "host": app_name,
-                            "http": {
-                                "paths": [
-                                    {
-                                        "path": "/",
-                                        "backend": {
-                                            "serviceName": app_name,
-                                            "servicePort": port,
-                                        },
-                                    }
-                                ]
-                            },
-                        }
-                    ]
-                },
-            }
-        ]
-
-        pod_ingress_resources = pod_spec._make_pod_ingress_resources(
-            config, app_name, port
-        )
-
-        self.assertListEqual(expected_result, pod_ingress_resources)
-
-    def test_make_pod_ingress_resources_with_whitelist_source_range(self) -> NoReturn:
-        """Testing make pod ingress resources with whitelist_source_range."""
-        config = {
-            "site_url": "http://nbi",
-            "max_file_size": 0,
-            "ingress_whitelist_source_range": "0.0.0.0/0",
-        }
-        app_name = "nbi"
-        port = 9999
-
-        expected_result = [
-            {
-                "name": f"{app_name}-ingress",
-                "annotations": {
-                    "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
-                    "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
-                    "nginx.ingress.kubernetes.io/ssl-redirect": "false",
-                    "nginx.ingress.kubernetes.io/whitelist-source-range": config[
-                        "ingress_whitelist_source_range"
-                    ],
-                },
-                "spec": {
-                    "rules": [
-                        {
-                            "host": app_name,
-                            "http": {
-                                "paths": [
-                                    {
-                                        "path": "/",
-                                        "backend": {
-                                            "serviceName": app_name,
-                                            "servicePort": port,
-                                        },
-                                    }
-                                ]
-                            },
-                        }
-                    ]
-                },
-            }
-        ]
-
-        pod_ingress_resources = pod_spec._make_pod_ingress_resources(
-            config, app_name, port
-        )
-
-        self.assertListEqual(expected_result, pod_ingress_resources)
-
-    def test_make_pod_ingress_resources_with_https(self) -> NoReturn:
-        """Testing make pod ingress resources with HTTPs."""
-        config = {
-            "site_url": "https://nbi",
-            "max_file_size": 0,
-            "ingress_whitelist_source_range": "",
-            "tls_secret_name": "",
-        }
-        app_name = "nbi"
-        port = 9999
-
-        expected_result = [
-            {
-                "name": f"{app_name}-ingress",
-                "annotations": {
-                    "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
-                    "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
-                },
-                "spec": {
-                    "rules": [
-                        {
-                            "host": app_name,
-                            "http": {
-                                "paths": [
-                                    {
-                                        "path": "/",
-                                        "backend": {
-                                            "serviceName": app_name,
-                                            "servicePort": port,
-                                        },
-                                    }
-                                ]
-                            },
-                        }
-                    ],
-                    "tls": [{"hosts": [app_name]}],
-                },
-            }
-        ]
-
-        pod_ingress_resources = pod_spec._make_pod_ingress_resources(
-            config, app_name, port
-        )
-
-        self.assertListEqual(expected_result, pod_ingress_resources)
-
-    def test_make_pod_ingress_resources_with_https_tls_secret_name(self) -> NoReturn:
-        """Testing make pod ingress resources with HTTPs and TLS secret name."""
-        config = {
-            "site_url": "https://nbi",
-            "max_file_size": 0,
-            "ingress_whitelist_source_range": "",
-            "tls_secret_name": "secret_name",
-        }
-        app_name = "nbi"
-        port = 9999
-
-        expected_result = [
-            {
-                "name": f"{app_name}-ingress",
-                "annotations": {
-                    "nginx.ingress.kubernetes.io/proxy-body-size": f"{config['max_file_size']}",
-                    "nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
-                },
-                "spec": {
-                    "rules": [
-                        {
-                            "host": app_name,
-                            "http": {
-                                "paths": [
-                                    {
-                                        "path": "/",
-                                        "backend": {
-                                            "serviceName": app_name,
-                                            "servicePort": port,
-                                        },
-                                    }
-                                ]
-                            },
-                        }
-                    ],
-                    "tls": [
-                        {"hosts": [app_name], "secretName": config["tls_secret_name"]}
-                    ],
-                },
-            }
-        ]
-
-        pod_ingress_resources = pod_spec._make_pod_ingress_resources(
-            config, app_name, port
-        )
-
-        self.assertListEqual(expected_result, pod_ingress_resources)
-
-    def test_make_startup_probe(self) -> NoReturn:
-        """Testing make startup probe."""
-        expected_result = {
-            "exec": {"command": ["/usr/bin/pgrep python3"]},
-            "initialDelaySeconds": 60,
-            "timeoutSeconds": 5,
-        }
-
-        startup_probe = pod_spec._make_startup_probe()
-
-        self.assertDictEqual(expected_result, startup_probe)
-
-    def test_make_readiness_probe(self) -> NoReturn:
-        """Testing make readiness probe."""
-        port = 9999
-
-        expected_result = {
-            "httpGet": {
-                "path": "/osm/",
-                "port": port,
-            },
-            "initialDelaySeconds": 45,
-            "timeoutSeconds": 5,
-        }
-
-        readiness_probe = pod_spec._make_readiness_probe(port)
-
-        self.assertDictEqual(expected_result, readiness_probe)
-
-    def test_make_liveness_probe(self) -> NoReturn:
-        """Testing make liveness probe."""
-        port = 9999
-
-        expected_result = {
-            "httpGet": {
-                "path": "/osm/",
-                "port": port,
-            },
-            "initialDelaySeconds": 45,
-            "timeoutSeconds": 5,
-        }
-
-        liveness_probe = pod_spec._make_liveness_probe(port)
-
-        self.assertDictEqual(expected_result, liveness_probe)
-
-    def test_make_pod_spec_without_image_info(self) -> NoReturn:
-        """Testing make pod spec without image_info."""
-        image_info = None
-        config = {
-            "enable_test": False,
-            "database_commonkey": "commonkey",
-            "log_level": "DEBUG",
-            "auth_backend": "internal",
-            "site_url": "",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-        app_name = "nbi"
-        port = 9999
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertIsNone(spec)
-
-    def test_make_pod_spec_without_config(self) -> NoReturn:
-        """Testing make pod spec without config."""
-        image_info = {"upstream-source": "opensourcemano/nbi:8"}
-        config = {}
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-        app_name = "nbi"
-        port = 9999
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-    def test_make_pod_spec_without_relation_state(self) -> NoReturn:
-        """Testing make pod spec without relation_state."""
-        image_info = {"upstream-source": "opensourcemano/nbi:8"}
-        config = {
-            "enable_test": False,
-            "database_commonkey": "commonkey",
-            "log_level": "DEBUG",
-            "auth_backend": "internal",
-            "site_url": "",
-        }
-        relation_state = {}
-        app_name = "nbi"
-        port = 9999
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-    def test_make_pod_spec(self) -> NoReturn:
-        """Testing make pod spec."""
-        image_info = {"upstream-source": "opensourcemano/nbi:8"}
-        config = {
-            "enable_test": False,
-            "database_commonkey": "commonkey",
-            "log_level": "DEBUG",
-            "auth_backend": "internal",
-            "site_url": "",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-        }
-        app_name = "nbi"
-        port = 9999
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": "nbi",
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "ALLOW_ANONYMOUS_LOGIN": "yes",
-                        "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
-                        "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
-                        "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
-                        "OSMNBI_MESSAGE_DRIVER": "kafka",
-                        "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
-                        "OSMNBI_DATABASE_DRIVER": "mongo",
-                        "OSMNBI_DATABASE_URI": relation_state["database_uri"],
-                        "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
-                        "OSMNBI_STORAGE_DRIVER": "mongo",
-                        "OSMNBI_STORAGE_PATH": "/app/storage",
-                        "OSMNBI_STORAGE_COLLECTION": "files",
-                        "OSMNBI_STORAGE_URI": relation_state["database_uri"],
-                        "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
-                        "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
-                        "OSMNBI_LOG_LEVEL": config["log_level"],
-                        "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
-                    },
-                }
-            ],
-            "kubernetesResources": {
-                "ingressResources": [],
-            },
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-    def test_make_pod_spec_with_keystone(self) -> NoReturn:
-        """Testing make pod spec with keystone."""
-        image_info = {"upstream-source": "opensourcemano/nbi:8"}
-        config = {
-            "enable_test": False,
-            "database_commonkey": "commonkey",
-            "log_level": "DEBUG",
-            "auth_backend": "keystone",
-            "site_url": "",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-            "prometheus_host": "prometheus",
-            "prometheus_port": 9082,
-            "keystone_host": "keystone",
-            "keystone_port": 5000,
-            "keystone_user_domain_name": "user_domain",
-            "keystone_project_domain_name": "project_domain",
-            "keystone_username": "username",
-            "keystone_password": "password",
-            "keystone_service": "service",
-        }
-        app_name = "nbi"
-        port = 9999
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": "nbi",
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "ALLOW_ANONYMOUS_LOGIN": "yes",
-                        "OSMNBI_SERVER_ENABLE_TEST": config["enable_test"],
-                        "OSMNBI_STATIC_DIR": "/app/osm_nbi/html_public",
-                        "OSMNBI_MESSAGE_HOST": relation_state["message_host"],
-                        "OSMNBI_MESSAGE_DRIVER": "kafka",
-                        "OSMNBI_MESSAGE_PORT": relation_state["message_port"],
-                        "OSMNBI_DATABASE_DRIVER": "mongo",
-                        "OSMNBI_DATABASE_URI": relation_state["database_uri"],
-                        "OSMNBI_DATABASE_COMMONKEY": config["database_commonkey"],
-                        "OSMNBI_STORAGE_DRIVER": "mongo",
-                        "OSMNBI_STORAGE_PATH": "/app/storage",
-                        "OSMNBI_STORAGE_COLLECTION": "files",
-                        "OSMNBI_STORAGE_URI": relation_state["database_uri"],
-                        "OSMNBI_PROMETHEUS_HOST": relation_state["prometheus_host"],
-                        "OSMNBI_PROMETHEUS_PORT": relation_state["prometheus_port"],
-                        "OSMNBI_LOG_LEVEL": config["log_level"],
-                        "OSMNBI_AUTHENTICATION_BACKEND": config["auth_backend"],
-                        "OSMNBI_AUTHENTICATION_AUTH_URL": relation_state[
-                            "keystone_host"
-                        ],
-                        "OSMNBI_AUTHENTICATION_AUTH_PORT": relation_state[
-                            "keystone_port"
-                        ],
-                        "OSMNBI_AUTHENTICATION_USER_DOMAIN_NAME": relation_state[
-                            "keystone_user_domain_name"
-                        ],
-                        "OSMNBI_AUTHENTICATION_PROJECT_DOMAIN_NAME": relation_state[
-                            "keystone_project_domain_name"
-                        ],
-                        "OSMNBI_AUTHENTICATION_SERVICE_USERNAME": relation_state[
-                            "keystone_username"
-                        ],
-                        "OSMNBI_AUTHENTICATION_SERVICE_PASSWORD": relation_state[
-                            "keystone_password"
-                        ],
-                        "OSMNBI_AUTHENTICATION_SERVICE_PROJECT": relation_state[
-                            "keystone_service"
-                        ],
-                    },
-                }
-            ],
-            "kubernetesResources": {
-                "ingressResources": [],
-            },
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/nbi/tox.ini b/installers/charm/nbi/tox.ini
deleted file mode 100644 (file)
index f3c9144..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-#######################################################################################
-
-[tox]
-envlist = black, cover, flake8, pylint, yamllint, safety
-skipsdist = true
-
-[tox:jenkins]
-toxworkdir = /tmp/.tox
-
-[testenv]
-basepython = python3.8
-setenv =
-  VIRTUAL_ENV={envdir}
-  PYTHONPATH = {toxinidir}:{toxinidir}/lib:{toxinidir}/src
-  PYTHONDONTWRITEBYTECODE = 1
-deps =  -r{toxinidir}/requirements.txt
-
-
-#######################################################################################
-[testenv:black]
-deps = black
-commands =
-        black --check --diff src/ tests/
-
-
-#######################################################################################
-[testenv:cover]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        coverage
-        nose2
-commands =
-        sh -c 'rm -f nosetests.xml'
-        coverage erase
-        nose2 -C --coverage src
-        coverage report --omit='*tests*'
-        coverage html -d ./cover --omit='*tests*'
-        coverage xml -o coverage.xml --omit=*tests*
-whitelist_externals = sh
-
-
-#######################################################################################
-[testenv:flake8]
-deps =  flake8
-        flake8-import-order
-commands =
-        flake8 src/ tests/
-
-
-#######################################################################################
-[testenv:pylint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        pylint==2.10.2
-commands =
-    pylint -E src/ tests/
-
-
-#######################################################################################
-[testenv:safety]
-setenv =
-        LC_ALL=C.UTF-8
-        LANG=C.UTF-8
-deps =  {[testenv]deps}
-        safety
-commands =
-        - safety check --full-report
-
-
-#######################################################################################
-[testenv:yamllint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        yamllint
-commands = yamllint .
-
-#######################################################################################
-[testenv:build]
-passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
-whitelist_externals =
-  charmcraft
-  sh
-commands =
-  charmcraft pack
-  sh -c 'ubuntu_version=20.04; \
-        architectures="amd64-aarch64-arm64"; \
-        charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \
-        mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm'
-
-#######################################################################################
-[flake8]
-ignore =
-        W291,
-        W293,
-        W503,
-        E123,
-        E125,
-        E226,
-        E241,
-exclude =
-        .git,
-        __pycache__,
-        .tox,
-max-line-length = 120
-show-source = True
-builtins = _
-max-complexity = 10
-import-order-style = google
diff --git a/installers/charm/ng-ui/.gitignore b/installers/charm/ng-ui/.gitignore
deleted file mode 100644 (file)
index 493739e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.stestr
-cover
-release
diff --git a/installers/charm/ng-ui/.jujuignore b/installers/charm/ng-ui/.jujuignore
deleted file mode 100644 (file)
index 3ae3e7d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.gitignore
-.stestr
-cover
-release
-tests/
-requirements*
-tox.ini
diff --git a/installers/charm/ng-ui/.yamllint.yaml b/installers/charm/ng-ui/.yamllint.yaml
deleted file mode 100644 (file)
index d71fb69..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
----
-extends: default
-
-yaml-files:
-  - "*.yaml"
-  - "*.yml"
-  - ".yamllint"
-ignore: |
-  .tox
-  cover/
-  build/
-  venv
-  release/
diff --git a/installers/charm/ng-ui/README.md b/installers/charm/ng-ui/README.md
deleted file mode 100644 (file)
index 9b77b5d..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<!-- #   Copyright 2020 Canonical Ltd.
-#
-#   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. -->
-
-# NG-UI Charm
-
-## How to deploy
-
-```bash
-juju deploy . # cs:~charmed-osm/ng-ui --channel edge
-juju relate ng-ui nbi
-```
-
-## How to expose the NG-UI through ingress
-
-```bash
-juju config ng-ui site_url=ng.<k8s_worker_ip>.xip.io
-juju expose ng-ui
-```
-
-> Note: The <k8s_worker_ip> is the IP of the K8s worker node. With microk8s, you can see the IP with `microk8s.config`. It is usually the IP of your host machine.
-
-## How to scale
-
-```bash
-    juju scale-application ng-ui 3
-```
-
-
-## Config Examples
-
-```bash
-juju config ng-ui image=opensourcemano/ng-ui:<tag>
-juju config ng-ui port=80
-juju config server_name=<name>
-juju config max_file_size=25
-```
diff --git a/installers/charm/ng-ui/charmcraft.yaml b/installers/charm/ng-ui/charmcraft.yaml
deleted file mode 100644 (file)
index 0a285a9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-type: charm
-bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: ["amd64"]
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-          - aarch64
-          - arm64
-parts:
-  charm:
-    build-packages: [git]
diff --git a/installers/charm/ng-ui/config.yaml b/installers/charm/ng-ui/config.yaml
deleted file mode 100644 (file)
index c5f447b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright 2020 Arctos Labs Scandinavia AB
-#
-# 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.
-
-options:
-  server_name:
-    description: Server name
-    type: string
-    default: localhost
-  port:
-    description: Port to expose
-    type: int
-    default: 80
-  max_file_size:
-    type: int
-    description: |
-      The maximum file size, in megabytes. If there is a reverse proxy in front
-      of Keystone, it may need to be configured to handle the requested size.
-      Note: if set to 0, there is no limit.
-    default: 0
-  ingress_class:
-    type: string
-    description: |
-      Ingress class name. This is useful for selecting the ingress to be used
-      in case there are multiple ingresses in the underlying k8s clusters.
-  ingress_whitelist_source_range:
-    type: string
-    description: |
-      A comma-separated list of CIDRs to store in the
-      ingress.kubernetes.io/whitelist-source-range annotation.
-    default: ""
-  tls_secret_name:
-    type: string
-    description: TLS Secret name
-    default: ""
-  site_url:
-    type: string
-    description: Ingress URL
-    default: ""
-  cluster_issuer:
-    type: string
-    description: Name of the cluster issuer for TLS certificates
-    default: ""
-  image_pull_policy:
-    type: string
-    description: |
-      ImagePullPolicy configuration for the pod.
-      Possible values: always, ifnotpresent, never
-    default: always
-  security_context:
-    description: Enables the security context of the pods
-    type: boolean
-    default: false
diff --git a/installers/charm/ng-ui/metadata.yaml b/installers/charm/ng-ui/metadata.yaml
deleted file mode 100644 (file)
index 60643b5..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#   Copyright 2020 Canonical Ltd.
-#
-#   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.
-
-name: osm-ng-ui
-summary: A Next Generation UI charm for Opensource MANO
-description: |
-  New UI for OSM
-series:
-  - kubernetes
-min-juju-version: 2.7.0
-deployment:
-  type: stateless
-  service: cluster
-requires:
-  nbi:
-    interface: http
-resources:
-  image:
-    type: oci-image
-    description: OSM docker image for NBI
-    upstream-source: "opensourcemano/ng-ui:latest"
diff --git a/installers/charm/ng-ui/requirements-test.txt b/installers/charm/ng-ui/requirements-test.txt
deleted file mode 100644 (file)
index cf61dd4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-mock==4.0.3
diff --git a/installers/charm/ng-ui/requirements.txt b/installers/charm/ng-ui/requirements.txt
deleted file mode 100644 (file)
index 10ade5d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-pydantic  # TODO: remove it
-git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master
\ No newline at end of file
diff --git a/installers/charm/ng-ui/src/charm.py b/installers/charm/ng-ui/src/charm.py
deleted file mode 100755 (executable)
index 39675d0..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213
-
-
-from ipaddress import ip_network
-import logging
-from pathlib import Path
-from string import Template
-from typing import NoReturn, Optional
-from urllib.parse import urlparse
-
-from ops.main import main
-from opslib.osm.charm import CharmedOsmBase, RelationsMissing
-from opslib.osm.interfaces.http import HttpClient
-from opslib.osm.pod import (
-    ContainerV3Builder,
-    FilesV3Builder,
-    IngressResourceV3Builder,
-    PodSpecV3Builder,
-)
-from opslib.osm.validator import ModelValidator, validator
-
-
-logger = logging.getLogger(__name__)
-
-
-class ConfigModel(ModelValidator):
-    port: int
-    server_name: str
-    max_file_size: int
-    site_url: Optional[str]
-    cluster_issuer: Optional[str]
-    ingress_class: Optional[str]
-    ingress_whitelist_source_range: Optional[str]
-    tls_secret_name: Optional[str]
-    image_pull_policy: str
-    security_context: bool
-
-    @validator("port")
-    def validate_port(cls, v):
-        if v <= 0:
-            raise ValueError("value must be greater than 0")
-        return v
-
-    @validator("max_file_size")
-    def validate_max_file_size(cls, v):
-        if v < 0:
-            raise ValueError("value must be equal or greater than 0")
-        return v
-
-    @validator("site_url")
-    def validate_site_url(cls, v):
-        if v:
-            parsed = urlparse(v)
-            if not parsed.scheme.startswith("http"):
-                raise ValueError("value must start with http")
-        return v
-
-    @validator("ingress_whitelist_source_range")
-    def validate_ingress_whitelist_source_range(cls, v):
-        if v:
-            ip_network(v)
-        return v
-
-    @validator("image_pull_policy")
-    def validate_image_pull_policy(cls, v):
-        values = {
-            "always": "Always",
-            "ifnotpresent": "IfNotPresent",
-            "never": "Never",
-        }
-        v = v.lower()
-        if v not in values.keys():
-            raise ValueError("value must be always, ifnotpresent or never")
-        return values[v]
-
-
-class NgUiCharm(CharmedOsmBase):
-    def __init__(self, *args) -> NoReturn:
-        super().__init__(*args, oci_image="image")
-
-        self.nbi_client = HttpClient(self, "nbi")
-        self.framework.observe(self.on["nbi"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["nbi"].relation_broken, self.configure_pod)
-
-    def _check_missing_dependencies(self, config: ConfigModel):
-        missing_relations = []
-
-        if self.nbi_client.is_missing_data_in_app():
-            missing_relations.append("nbi")
-
-        if missing_relations:
-            raise RelationsMissing(missing_relations)
-
-    def _build_files(self, config: ConfigModel):
-        files_builder = FilesV3Builder()
-        files_builder.add_file(
-            "default",
-            Template(Path("templates/default.template").read_text()).substitute(
-                port=config.port,
-                server_name=config.server_name,
-                max_file_size=config.max_file_size,
-                nbi_host=self.nbi_client.host,
-                nbi_port=self.nbi_client.port,
-            ),
-        )
-        return files_builder.build()
-
-    def build_pod_spec(self, image_info):
-        # Validate config
-        config = ConfigModel(**dict(self.config))
-        # Check relations
-        self._check_missing_dependencies(config)
-        # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder(
-            enable_security_context=config.security_context
-        )
-        # Build Container
-        container_builder = ContainerV3Builder(
-            self.app.name,
-            image_info,
-            config.image_pull_policy,
-            run_as_non_root=config.security_context,
-        )
-        container_builder.add_port(name=self.app.name, port=config.port)
-        container = container_builder.build()
-        container_builder.add_tcpsocket_readiness_probe(
-            config.port,
-            initial_delay_seconds=45,
-            timeout_seconds=5,
-        )
-        container_builder.add_tcpsocket_liveness_probe(
-            config.port,
-            initial_delay_seconds=45,
-            timeout_seconds=15,
-        )
-        container_builder.add_volume_config(
-            "configuration",
-            "/etc/nginx/sites-available/",
-            self._build_files(config),
-        )
-        # Add container to pod spec
-        pod_spec_builder.add_container(container)
-        # Add ingress resources to pod spec if site url exists
-        if config.site_url:
-            parsed = urlparse(config.site_url)
-            annotations = {
-                "nginx.ingress.kubernetes.io/proxy-body-size": "{}".format(
-                    str(config.max_file_size) + "m"
-                    if config.max_file_size > 0
-                    else config.max_file_size
-                )
-            }
-            if config.ingress_class:
-                annotations["kubernetes.io/ingress.class"] = config.ingress_class
-            ingress_resource_builder = IngressResourceV3Builder(
-                f"{self.app.name}-ingress", annotations
-            )
-
-            if config.ingress_whitelist_source_range:
-                annotations[
-                    "nginx.ingress.kubernetes.io/whitelist-source-range"
-                ] = config.ingress_whitelist_source_range
-
-            if config.cluster_issuer:
-                annotations["cert-manager.io/cluster-issuer"] = config.cluster_issuer
-
-            if parsed.scheme == "https":
-                ingress_resource_builder.add_tls(
-                    [parsed.hostname], config.tls_secret_name
-                )
-            else:
-                annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
-
-            ingress_resource_builder.add_rule(
-                parsed.hostname, self.app.name, config.port
-            )
-            ingress_resource = ingress_resource_builder.build()
-            pod_spec_builder.add_ingress_resource(ingress_resource)
-        return pod_spec_builder.build()
-
-
-if __name__ == "__main__":
-    main(NgUiCharm)
diff --git a/installers/charm/ng-ui/src/pod_spec.py b/installers/charm/ng-ui/src/pod_spec.py
deleted file mode 100644 (file)
index 95d5f72..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213,E0611
-
-
-import logging
-from pydantic import (
-    BaseModel,
-    conint,
-    IPvAnyNetwork,
-    PositiveInt,
-    validator,
-)
-from typing import Any, Dict, List, Optional
-from urllib.parse import urlparse
-from pathlib import Path
-from string import Template
-
-logger = logging.getLogger(__name__)
-
-
-class ConfigData(BaseModel):
-    """Configuration data model."""
-
-    port: PositiveInt
-    site_url: Optional[str]
-    max_file_size: Optional[conint(ge=0)]
-    ingress_whitelist_source_range: Optional[IPvAnyNetwork]
-    tls_secret_name: Optional[str]
-
-    @validator("max_file_size", pre=True, always=True)
-    def validate_max_file_size(cls, value, values, **kwargs):
-        site_url = values.get("site_url")
-
-        if not site_url:
-            return value
-
-        parsed = urlparse(site_url)
-
-        if not parsed.scheme.startswith("http"):
-            return value
-
-        if value is None:
-            raise ValueError("max_file_size needs to be defined if site_url is defined")
-
-        return value
-
-    @validator("ingress_whitelist_source_range", pre=True, always=True)
-    def validate_ingress_whitelist_source_range(cls, value, values, **kwargs):
-        if not value:
-            return None
-
-        return value
-
-
-class RelationData(BaseModel):
-    """Relation data model."""
-
-    nbi_host: str
-    nbi_port: PositiveInt
-
-
-def _make_pod_ports(port: int) -> List[Dict[str, Any]]:
-    """Generate pod ports details.
-
-    Args:
-        port (int): Port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod port details.
-    """
-    return [
-        {"name": "http", "containerPort": port, "protocol": "TCP"},
-    ]
-
-
-def _make_pod_ingress_resources(
-    config: Dict[str, Any], app_name: str, port: int
-) -> List[Dict[str, Any]]:
-    """Generate pod ingress resources.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-        app_name (str): application name.
-        port (int): port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod ingress resources.
-    """
-    site_url = config.get("site_url")
-
-    if not site_url:
-        return
-
-    parsed = urlparse(site_url)
-
-    if not parsed.scheme.startswith("http"):
-        return
-
-    max_file_size = config["max_file_size"]
-    ingress_whitelist_source_range = config["ingress_whitelist_source_range"]
-
-    annotations = {
-        "nginx.ingress.kubernetes.io/proxy-body-size": "{}".format(
-            str(max_file_size) + "m" if max_file_size > 0 else max_file_size
-        ),
-    }
-
-    if ingress_whitelist_source_range:
-        annotations[
-            "nginx.ingress.kubernetes.io/whitelist-source-range"
-        ] = ingress_whitelist_source_range
-
-    ingress_spec_tls = None
-
-    if parsed.scheme == "https":
-        ingress_spec_tls = [{"hosts": [parsed.hostname]}]
-        tls_secret_name = config["tls_secret_name"]
-        if tls_secret_name:
-            ingress_spec_tls[0]["secretName"] = tls_secret_name
-    else:
-        annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
-
-    ingress = {
-        "name": "{}-ingress".format(app_name),
-        "annotations": annotations,
-        "spec": {
-            "rules": [
-                {
-                    "host": parsed.hostname,
-                    "http": {
-                        "paths": [
-                            {
-                                "path": "/",
-                                "backend": {
-                                    "serviceName": app_name,
-                                    "servicePort": port,
-                                },
-                            }
-                        ]
-                    },
-                }
-            ]
-        },
-    }
-    if ingress_spec_tls:
-        ingress["spec"]["tls"] = ingress_spec_tls
-
-    return [ingress]
-
-
-def _make_startup_probe() -> Dict[str, Any]:
-    """Generate startup probe.
-
-    Returns:
-        Dict[str, Any]: startup probe.
-    """
-    return {
-        "exec": {"command": ["/usr/bin/pgrep python3"]},
-        "initialDelaySeconds": 60,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_readiness_probe(port: int) -> Dict[str, Any]:
-    """Generate readiness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: readiness probe.
-    """
-    return {
-        "tcpSocket": {
-            "port": port,
-        },
-        "initialDelaySeconds": 45,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_liveness_probe(port: int) -> Dict[str, Any]:
-    """Generate liveness probe.
-
-    Args:
-        port (int): [description]
-
-    Returns:
-        Dict[str, Any]: liveness probe.
-    """
-    return {
-        "tcpSocket": {
-            "port": port,
-        },
-        "initialDelaySeconds": 45,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_pod_volume_config(
-    config: Dict[str, Any],
-    relation_state: Dict[str, Any],
-) -> List[Dict[str, Any]]:
-    """Generate volume config with files.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-
-    Returns:
-        Dict[str, Any]: volume config.
-    """
-    template_data = {**config, **relation_state}
-    template_data["max_file_size"] = f'{template_data["max_file_size"]}M'
-    return [
-        {
-            "name": "configuration",
-            "mountPath": "/etc/nginx/sites-available/",
-            "files": [
-                {
-                    "path": "default",
-                    "content": Template(Path("files/default").read_text()).substitute(
-                        template_data
-                    ),
-                }
-            ],
-        }
-    ]
-
-
-def make_pod_spec(
-    image_info: Dict[str, str],
-    config: Dict[str, Any],
-    relation_state: Dict[str, Any],
-    app_name: str = "ng-ui",
-) -> Dict[str, Any]:
-    """Generate the pod spec information.
-
-    Args:
-        image_info (Dict[str, str]): Object provided by
-                                     OCIImageResource("image").fetch().
-        config (Dict[str, Any]): Configuration information.
-        relation_state (Dict[str, Any]): Relation state information.
-        app_name (str, optional): Application name. Defaults to "ng-ui".
-        port (int, optional): Port for the container. Defaults to 80.
-
-    Returns:
-        Dict[str, Any]: Pod spec dictionary for the charm.
-    """
-    if not image_info:
-        return None
-
-    ConfigData(**(config))
-    RelationData(**(relation_state))
-
-    ports = _make_pod_ports(config["port"])
-    ingress_resources = _make_pod_ingress_resources(config, app_name, config["port"])
-    kubernetes = {
-        # "startupProbe": _make_startup_probe(),
-        "readinessProbe": _make_readiness_probe(config["port"]),
-        "livenessProbe": _make_liveness_probe(config["port"]),
-    }
-    volume_config = _make_pod_volume_config(config, relation_state)
-    return {
-        "version": 3,
-        "containers": [
-            {
-                "name": app_name,
-                "imageDetails": image_info,
-                "imagePullPolicy": "Always",
-                "ports": ports,
-                "kubernetes": kubernetes,
-                "volumeConfig": volume_config,
-            }
-        ],
-        "kubernetesResources": {
-            "ingressResources": ingress_resources or [],
-        },
-    }
diff --git a/installers/charm/ng-ui/templates/default.template b/installers/charm/ng-ui/templates/default.template
deleted file mode 100644 (file)
index f946263..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#   Copyright 2020 Canonical Ltd.
-#
-#   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.
-
-
-
-server {
-    listen       $port;
-    server_name  $server_name;
-    root   /usr/share/nginx/html;
-    index  index.html index.htm;
-    client_max_body_size $max_file_size;
-
-    location /osm {
-        proxy_pass https://$nbi_host:$nbi_port;
-        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
-        proxy_set_header Accept-Encoding "";
-    }
-
-    location / {
-        try_files $$uri $$uri/ /index.html;
-    }
-}
diff --git a/installers/charm/ng-ui/tests/__init__.py b/installers/charm/ng-ui/tests/__init__.py
deleted file mode 100644 (file)
index 446d5ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-"""Init mocking for unit tests."""
-
-import sys
-
-
-import mock
-
-
-class OCIImageResourceErrorMock(Exception):
-    pass
-
-
-sys.path.append("src")
-
-oci_image = mock.MagicMock()
-oci_image.OCIImageResourceError = OCIImageResourceErrorMock
-sys.modules["oci_image"] = oci_image
-sys.modules["oci_image"].OCIImageResource().fetch.return_value = {}
diff --git a/installers/charm/ng-ui/tests/test_charm.py b/installers/charm/ng-ui/tests/test_charm.py
deleted file mode 100644 (file)
index 2765e81..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import sys
-from typing import NoReturn
-import unittest
-
-from charm import NgUiCharm
-from ops.model import ActiveStatus, BlockedStatus
-from ops.testing import Harness
-
-
-class TestCharm(unittest.TestCase):
-    """Prometheus Charm unit tests."""
-
-    def setUp(self) -> NoReturn:
-        """Test setup"""
-        self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
-        self.harness = Harness(NgUiCharm)
-        self.harness.set_leader(is_leader=True)
-        self.harness.begin()
-        self.config = {
-            "server_name": "localhost",
-            "port": 80,
-            "max_file_size": 0,
-            "ingress_whitelist_source_range": "",
-            "tls_secret_name": "",
-            "site_url": "https://ui.192.168.100.100.nip.io",
-            "cluster_issuer": "vault-issuer",
-        }
-        self.harness.update_config(self.config)
-
-    def test_config_changed_no_relations(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["nbi"]
-            )
-        )
-
-    def test_config_changed_non_leader(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-        self.harness.set_leader(is_leader=False)
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-    def test_with_relations(
-        self,
-    ) -> NoReturn:
-        "Test with relations (internal)"
-        self.initialize_nbi_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def initialize_nbi_relation(self):
-        http_relation_id = self.harness.add_relation("nbi", "nbi")
-        self.harness.add_relation_unit(http_relation_id, "nbi")
-        self.harness.update_relation_data(
-            http_relation_id,
-            "nbi",
-            {"host": "nbi", "port": 9999},
-        )
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/ng-ui/tox.ini b/installers/charm/ng-ui/tox.ini
deleted file mode 100644 (file)
index 58e13a6..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-#######################################################################################
-
-[tox]
-envlist = black, cover, flake8, pylint, yamllint, safety
-skipsdist = true
-
-[tox:jenkins]
-toxworkdir = /tmp/.tox
-
-[testenv]
-basepython = python3.8
-setenv = VIRTUAL_ENV={envdir}
-         PYTHONDONTWRITEBYTECODE = 1
-deps =  -r{toxinidir}/requirements.txt
-
-
-#######################################################################################
-[testenv:black]
-deps = black
-commands =
-        black --check --diff src/ tests/
-
-
-#######################################################################################
-[testenv:cover]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        coverage
-        nose2
-commands =
-        sh -c 'rm -f nosetests.xml'
-        coverage erase
-        nose2 -C --coverage src
-        coverage report --omit='*tests*'
-        coverage html -d ./cover --omit='*tests*'
-        coverage xml -o coverage.xml --omit=*tests*
-whitelist_externals = sh
-
-
-#######################################################################################
-[testenv:flake8]
-deps =  flake8
-        flake8-import-order
-commands =
-        flake8 src/ tests/ --exclude=*pod_spec*
-
-
-#######################################################################################
-[testenv:pylint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        pylint==2.10.2
-commands =
-    pylint -E src/ tests/
-
-
-#######################################################################################
-[testenv:safety]
-setenv =
-        LC_ALL=C.UTF-8
-        LANG=C.UTF-8
-deps =  {[testenv]deps}
-        safety
-commands =
-        - safety check --full-report
-
-
-#######################################################################################
-[testenv:yamllint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        yamllint
-commands = yamllint .
-
-#######################################################################################
-[testenv:build]
-passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
-whitelist_externals =
-  charmcraft
-  sh
-commands =
-  charmcraft pack
-  sh -c 'ubuntu_version=20.04; \
-        architectures="amd64-aarch64-arm64"; \
-        charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \
-        mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm'
-
-#######################################################################################
-[flake8]
-ignore =
-        W291,
-        W293,
-        W503,
-        E123,
-        E125,
-        E226,
-        E241,
-exclude =
-        .git,
-        __pycache__,
-        .tox,
-max-line-length = 120
-show-source = True
-builtins = _
-max-complexity = 10
-import-order-style = google
diff --git a/installers/charm/pla/.gitignore b/installers/charm/pla/.gitignore
deleted file mode 100644 (file)
index 493739e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.stestr
-cover
-release
diff --git a/installers/charm/pla/.jujuignore b/installers/charm/pla/.jujuignore
deleted file mode 100644 (file)
index 3ae3e7d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.gitignore
-.stestr
-cover
-release
-tests/
-requirements*
-tox.ini
diff --git a/installers/charm/pla/.yamllint.yaml b/installers/charm/pla/.yamllint.yaml
deleted file mode 100644 (file)
index d71fb69..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
----
-extends: default
-
-yaml-files:
-  - "*.yaml"
-  - "*.yml"
-  - ".yamllint"
-ignore: |
-  .tox
-  cover/
-  build/
-  venv
-  release/
diff --git a/installers/charm/pla/README.md b/installers/charm/pla/README.md
deleted file mode 100644 (file)
index 8d486d0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<!-- #   Copyright 2020 Canonical Ltd.
-#
-#   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. -->
-# PLA Charm
\ No newline at end of file
diff --git a/installers/charm/pla/charmcraft.yaml b/installers/charm/pla/charmcraft.yaml
deleted file mode 100644 (file)
index 0a285a9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-type: charm
-bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: ["amd64"]
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-          - aarch64
-          - arm64
-parts:
-  charm:
-    build-packages: [git]
diff --git a/installers/charm/pla/config.yaml b/installers/charm/pla/config.yaml
deleted file mode 100644 (file)
index 642c165..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright 2020 Arctos Labs Scandinavia AB
-#
-# 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.
-
-options:
-  log_level:
-    description: Log level
-    type: string
-    default: INFO
-  database_commonkey:
-    description: Common Key for Mongo database
-    type: string
-    default: osm
-  mongodb_uri:
-    type: string
-    description: MongoDB URI (external database)
-  image_pull_policy:
-    type: string
-    description: |
-      ImagePullPolicy configuration for the pod.
-      Possible values: always, ifnotpresent, never
-    default: always
-  security_context:
-    description: Enables the security context of the pods
-    type: boolean
-    default: false
diff --git a/installers/charm/pla/lib/charms/kafka_k8s/v0/kafka.py b/installers/charm/pla/lib/charms/kafka_k8s/v0/kafka.py
deleted file mode 100644 (file)
index 1baf9a8..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2022 Canonical Ltd.
-# See LICENSE file for licensing details.
-#
-# 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.
-
-"""Kafka library.
-
-This [library](https://juju.is/docs/sdk/libraries) implements both sides of the
-`kafka` [interface](https://juju.is/docs/sdk/relations).
-
-The *provider* side of this interface is implemented by the
-[kafka-k8s Charmed Operator](https://charmhub.io/kafka-k8s).
-
-Any Charmed Operator that *requires* Kafka for providing its
-service should implement the *requirer* side of this interface.
-
-In a nutshell using this library to implement a Charmed Operator *requiring*
-Kafka would look like
-
-```
-$ charmcraft fetch-lib charms.kafka_k8s.v0.kafka
-```
-
-`metadata.yaml`:
-
-```
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-```
-
-`src/charm.py`:
-
-```
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.charm import CharmBase
-
-
-class MyCharm(CharmBase):
-
-    on = KafkaEvents()
-
-    def __init__(self, *args):
-        super().__init__(*args)
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(
-            self.on.kafka_available,
-            self._on_kafka_available,
-        )
-        self.framework.observe(
-            self.on.kafka_broken,
-            self._on_kafka_broken,
-        )
-
-    def _on_kafka_available(self, event):
-        # Get Kafka host and port
-        host: str = self.kafka.host
-        port: int = self.kafka.port
-        # host => "kafka-k8s"
-        # port => 9092
-
-    def _on_kafka_broken(self, event):
-        # Stop service
-        # ...
-        self.unit.status = BlockedStatus("need kafka relation")
-```
-
-You can file bugs
-[here](https://github.com/charmed-osm/kafka-k8s-operator/issues)!
-"""
-
-from typing import Optional
-
-from ops.charm import CharmBase, CharmEvents
-from ops.framework import EventBase, EventSource, Object
-
-# The unique Charmhub library identifier, never change it
-from ops.model import Relation
-
-LIBID = "eacc8c85082347c9aae740e0220b8376"
-
-# Increment this major API version when introducing breaking changes
-LIBAPI = 0
-
-# Increment this PATCH version before using `charmcraft publish-lib` or reset
-# to 0 if you are raising the major API version
-LIBPATCH = 3
-
-
-KAFKA_HOST_APP_KEY = "host"
-KAFKA_PORT_APP_KEY = "port"
-
-
-class _KafkaAvailableEvent(EventBase):
-    """Event emitted when Kafka is available."""
-
-
-class _KafkaBrokenEvent(EventBase):
-    """Event emitted when Kafka relation is broken."""
-
-
-class KafkaEvents(CharmEvents):
-    """Kafka events.
-
-    This class defines the events that Kafka can emit.
-
-    Events:
-        kafka_available (_KafkaAvailableEvent)
-    """
-
-    kafka_available = EventSource(_KafkaAvailableEvent)
-    kafka_broken = EventSource(_KafkaBrokenEvent)
-
-
-class KafkaRequires(Object):
-    """Requires-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self.charm = charm
-        self._endpoint_name = endpoint_name
-
-        # Observe relation events
-        event_observe_mapping = {
-            charm.on[self._endpoint_name].relation_changed: self._on_relation_changed,
-            charm.on[self._endpoint_name].relation_broken: self._on_relation_broken,
-        }
-        for event, observer in event_observe_mapping.items():
-            self.framework.observe(event, observer)
-
-    def _on_relation_changed(self, event) -> None:
-        if event.relation.app and all(
-            key in event.relation.data[event.relation.app]
-            for key in (KAFKA_HOST_APP_KEY, KAFKA_PORT_APP_KEY)
-        ):
-            self.charm.on.kafka_available.emit()
-
-    def _on_relation_broken(self, _) -> None:
-        self.charm.on.kafka_broken.emit()
-
-    @property
-    def host(self) -> str:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            relation.data[relation.app].get(KAFKA_HOST_APP_KEY)
-            if relation and relation.app
-            else None
-        )
-
-    @property
-    def port(self) -> int:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            int(relation.data[relation.app].get(KAFKA_PORT_APP_KEY))
-            if relation and relation.app
-            else None
-        )
-
-
-class KafkaProvides(Object):
-    """Provides-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self._endpoint_name = endpoint_name
-
-    def set_host_info(self, host: str, port: int, relation: Optional[Relation] = None) -> None:
-        """Set Kafka host and port.
-
-        This function writes in the application data of the relation, therefore,
-        only the unit leader can call it.
-
-        Args:
-            host (str): Kafka hostname or IP address.
-            port (int): Kafka port.
-            relation (Optional[Relation]): Relation to update.
-                                           If not specified, all relations will be updated.
-
-        Raises:
-            Exception: if a non-leader unit calls this function.
-        """
-        if not self.model.unit.is_leader():
-            raise Exception("only the leader set host information.")
-
-        if relation:
-            self._update_relation_data(host, port, relation)
-            return
-
-        for relation in self.model.relations[self._endpoint_name]:
-            self._update_relation_data(host, port, relation)
-
-    def _update_relation_data(self, host: str, port: int, relation: Relation) -> None:
-        """Update data in relation if needed."""
-        relation.data[self.model.app][KAFKA_HOST_APP_KEY] = host
-        relation.data[self.model.app][KAFKA_PORT_APP_KEY] = str(port)
diff --git a/installers/charm/pla/metadata.yaml b/installers/charm/pla/metadata.yaml
deleted file mode 100644 (file)
index bd8b279..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#   Copyright 2020 Canonical Ltd.
-#
-#   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.
-
-name: osm-pla
-summary: A Placement charm for Opensource MANO
-description: |
-  Placement module for OSM
-series:
-  - kubernetes
-min-juju-version: 2.7.0
-deployment:
-  type: stateless
-  service: cluster
-resources:
-  image:
-    type: oci-image
-    description: OSM docker image for POL
-    upstream-source: "opensourcemano/pla:latest"
-requires:
-  kafka:
-    interface: kafka
-  mongodb:
-    interface: mongodb
diff --git a/installers/charm/pla/requirements-test.txt b/installers/charm/pla/requirements-test.txt
deleted file mode 100644 (file)
index cf61dd4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-mock==4.0.3
diff --git a/installers/charm/pla/requirements.txt b/installers/charm/pla/requirements.txt
deleted file mode 100644 (file)
index 1a8928c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master
\ No newline at end of file
diff --git a/installers/charm/pla/src/charm.py b/installers/charm/pla/src/charm.py
deleted file mode 100755 (executable)
index d907f0b..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213
-
-
-import logging
-from typing import NoReturn, Optional
-
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.main import main
-from opslib.osm.charm import CharmedOsmBase, RelationsMissing
-from opslib.osm.interfaces.mongo import MongoClient
-from opslib.osm.pod import (
-    ContainerV3Builder,
-    PodRestartPolicy,
-    PodSpecV3Builder,
-)
-from opslib.osm.validator import ModelValidator, validator
-
-
-logger = logging.getLogger(__name__)
-
-PORT = 9999
-
-
-class ConfigModel(ModelValidator):
-    database_commonkey: str
-    mongodb_uri: Optional[str]
-    log_level: str
-    image_pull_policy: str
-    security_context: bool
-
-    @validator("log_level")
-    def validate_log_level(cls, v):
-        if v not in {"INFO", "DEBUG"}:
-            raise ValueError("value must be INFO or DEBUG")
-        return v
-
-    @validator("mongodb_uri")
-    def validate_mongodb_uri(cls, v):
-        if v and not v.startswith("mongodb://"):
-            raise ValueError("mongodb_uri is not properly formed")
-        return v
-
-    @validator("image_pull_policy")
-    def validate_image_pull_policy(cls, v):
-        values = {
-            "always": "Always",
-            "ifnotpresent": "IfNotPresent",
-            "never": "Never",
-        }
-        v = v.lower()
-        if v not in values.keys():
-            raise ValueError("value must be always, ifnotpresent or never")
-        return values[v]
-
-
-class PlaCharm(CharmedOsmBase):
-    on = KafkaEvents()
-
-    def __init__(self, *args) -> NoReturn:
-        super().__init__(*args, oci_image="image")
-
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(self.on.kafka_available, self.configure_pod)
-        self.framework.observe(self.on.kafka_broken, self.configure_pod)
-
-        self.mongodb_client = MongoClient(self, "mongodb")
-        self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
-
-    def _check_missing_dependencies(self, config: ConfigModel):
-        missing_relations = []
-
-        if not self.kafka.host or not self.kafka.port:
-            missing_relations.append("kafka")
-        if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
-            missing_relations.append("mongodb")
-
-        if missing_relations:
-            raise RelationsMissing(missing_relations)
-
-    def build_pod_spec(self, image_info):
-        # Validate config
-        config = ConfigModel(**dict(self.config))
-
-        if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
-            raise Exception("Mongodb data cannot be provided via config and relation")
-
-        # Check relations
-        self._check_missing_dependencies(config)
-
-        # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder(
-            enable_security_context=config.security_context
-        )
-
-        # Add secrets to the pod
-        mongodb_secret_name = f"{self.app.name}-mongodb-secret"
-        pod_spec_builder.add_secret(
-            mongodb_secret_name,
-            {
-                "uri": config.mongodb_uri or self.mongodb_client.connection_string,
-                "commonkey": config.database_commonkey,
-            },
-        )
-
-        # Build Container
-        container_builder = ContainerV3Builder(
-            self.app.name,
-            image_info,
-            config.image_pull_policy,
-            run_as_non_root=config.security_context,
-        )
-        container_builder.add_port(name=self.app.name, port=PORT)
-        container_builder.add_envs(
-            {
-                # General configuration
-                "ALLOW_ANONYMOUS_LOGIN": "yes",
-                "OSMPLA_GLOBAL_LOG_LEVEL": config.log_level,
-                # Kafka configuration
-                "OSMPLA_MESSAGE_DRIVER": "kafka",
-                "OSMPLA_MESSAGE_HOST": self.kafka.host,
-                "OSMPLA_MESSAGE_PORT": self.kafka.port,
-                # Database configuration
-                "OSMPLA_DATABASE_DRIVER": "mongo",
-            }
-        )
-
-        container_builder.add_secret_envs(
-            secret_name=mongodb_secret_name,
-            envs={
-                "OSMPLA_DATABASE_URI": "uri",
-                "OSMPLA_DATABASE_COMMONKEY": "commonkey",
-            },
-        )
-
-        container = container_builder.build()
-
-        # Add Pod restart policy
-        restart_policy = PodRestartPolicy()
-        restart_policy.add_secrets(secret_names=(mongodb_secret_name,))
-        pod_spec_builder.set_restart_policy(restart_policy)
-
-        # Add container to pod spec
-        pod_spec_builder.add_container(container)
-
-        return pod_spec_builder.build()
-
-
-if __name__ == "__main__":
-    main(PlaCharm)
diff --git a/installers/charm/pla/tests/__init__.py b/installers/charm/pla/tests/__init__.py
deleted file mode 100644 (file)
index 446d5ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-"""Init mocking for unit tests."""
-
-import sys
-
-
-import mock
-
-
-class OCIImageResourceErrorMock(Exception):
-    pass
-
-
-sys.path.append("src")
-
-oci_image = mock.MagicMock()
-oci_image.OCIImageResourceError = OCIImageResourceErrorMock
-sys.modules["oci_image"] = oci_image
-sys.modules["oci_image"].OCIImageResource().fetch.return_value = {}
diff --git a/installers/charm/pla/tests/test_charm.py b/installers/charm/pla/tests/test_charm.py
deleted file mode 100644 (file)
index d577e9f..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import sys
-from typing import NoReturn
-import unittest
-
-
-from charm import PlaCharm
-from ops.model import ActiveStatus, BlockedStatus
-from ops.testing import Harness
-
-
-class TestCharm(unittest.TestCase):
-    """Pla Charm unit tests."""
-
-    def setUp(self) -> NoReturn:
-        """Test setup"""
-        self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
-        self.harness = Harness(PlaCharm)
-        self.harness.set_leader(is_leader=True)
-        self.harness.begin()
-        self.config = {
-            "log_level": "INFO",
-            "mongodb_uri": "",
-        }
-        self.harness.update_config(self.config)
-
-    def test_config_changed_no_relations(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["mongodb", "kafka"]
-            )
-        )
-
-    def test_config_changed_non_leader(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-        self.harness.set_leader(is_leader=False)
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-    def test_with_relations_and_mongodb_config(
-        self,
-    ) -> NoReturn:
-        "Test with relations and mongodb config (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_config()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations(
-        self,
-    ) -> NoReturn:
-        "Test with relations (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_exception_mongodb_relation_and_config(
-        self,
-    ) -> NoReturn:
-        "Test with relation and config for Mongodb. Test must fail"
-        self.initialize_mongo_relation()
-        self.initialize_mongo_config()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def initialize_kafka_relation(self):
-        kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-        self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-        self.harness.update_relation_data(
-            kafka_relation_id, "kafka", {"host": "kafka", "port": 9092}
-        )
-
-    def initialize_mongo_config(self):
-        self.harness.update_config({"mongodb_uri": "mongodb://mongo:27017"})
-
-    def initialize_mongo_relation(self):
-        mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-        self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mongodb/0",
-            {"connection_string": "mongodb://mongo:27017"},
-        )
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/pla/tox.ini b/installers/charm/pla/tox.ini
deleted file mode 100644 (file)
index f3c9144..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-#######################################################################################
-
-[tox]
-envlist = black, cover, flake8, pylint, yamllint, safety
-skipsdist = true
-
-[tox:jenkins]
-toxworkdir = /tmp/.tox
-
-[testenv]
-basepython = python3.8
-setenv =
-  VIRTUAL_ENV={envdir}
-  PYTHONPATH = {toxinidir}:{toxinidir}/lib:{toxinidir}/src
-  PYTHONDONTWRITEBYTECODE = 1
-deps =  -r{toxinidir}/requirements.txt
-
-
-#######################################################################################
-[testenv:black]
-deps = black
-commands =
-        black --check --diff src/ tests/
-
-
-#######################################################################################
-[testenv:cover]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        coverage
-        nose2
-commands =
-        sh -c 'rm -f nosetests.xml'
-        coverage erase
-        nose2 -C --coverage src
-        coverage report --omit='*tests*'
-        coverage html -d ./cover --omit='*tests*'
-        coverage xml -o coverage.xml --omit=*tests*
-whitelist_externals = sh
-
-
-#######################################################################################
-[testenv:flake8]
-deps =  flake8
-        flake8-import-order
-commands =
-        flake8 src/ tests/
-
-
-#######################################################################################
-[testenv:pylint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        pylint==2.10.2
-commands =
-    pylint -E src/ tests/
-
-
-#######################################################################################
-[testenv:safety]
-setenv =
-        LC_ALL=C.UTF-8
-        LANG=C.UTF-8
-deps =  {[testenv]deps}
-        safety
-commands =
-        - safety check --full-report
-
-
-#######################################################################################
-[testenv:yamllint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        yamllint
-commands = yamllint .
-
-#######################################################################################
-[testenv:build]
-passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
-whitelist_externals =
-  charmcraft
-  sh
-commands =
-  charmcraft pack
-  sh -c 'ubuntu_version=20.04; \
-        architectures="amd64-aarch64-arm64"; \
-        charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \
-        mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm'
-
-#######################################################################################
-[flake8]
-ignore =
-        W291,
-        W293,
-        W503,
-        E123,
-        E125,
-        E226,
-        E241,
-exclude =
-        .git,
-        __pycache__,
-        .tox,
-max-line-length = 120
-show-source = True
-builtins = _
-max-complexity = 10
-import-order-style = google
diff --git a/installers/charm/pol/.gitignore b/installers/charm/pol/.gitignore
deleted file mode 100644 (file)
index 2885df2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.stestr
-cover
-release
\ No newline at end of file
diff --git a/installers/charm/pol/.jujuignore b/installers/charm/pol/.jujuignore
deleted file mode 100644 (file)
index 3ae3e7d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.gitignore
-.stestr
-cover
-release
-tests/
-requirements*
-tox.ini
diff --git a/installers/charm/pol/.yamllint.yaml b/installers/charm/pol/.yamllint.yaml
deleted file mode 100644 (file)
index d71fb69..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
----
-extends: default
-
-yaml-files:
-  - "*.yaml"
-  - "*.yml"
-  - ".yamllint"
-ignore: |
-  .tox
-  cover/
-  build/
-  venv
-  release/
diff --git a/installers/charm/pol/README.md b/installers/charm/pol/README.md
deleted file mode 100644 (file)
index 12e60df..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<!-- Copyright 2020 Canonical Ltd.
-
-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.
-
-For those usages not covered by the Apache License, Version 2.0 please
-contact: legal@canonical.com
-
-To get in touch with the maintainers, please contact:
-osm-charmers@lists.launchpad.net -->
-
-# POL operator Charm for Kubernetes
-
-## Requirements
diff --git a/installers/charm/pol/charmcraft.yaml b/installers/charm/pol/charmcraft.yaml
deleted file mode 100644 (file)
index 0a285a9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-type: charm
-bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: ["amd64"]
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-          - aarch64
-          - arm64
-parts:
-  charm:
-    build-packages: [git]
diff --git a/installers/charm/pol/config.yaml b/installers/charm/pol/config.yaml
deleted file mode 100644 (file)
index a2eef47..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-options:
-  log_level:
-    description: "Log Level"
-    type: string
-    default: "INFO"
-  mongodb_uri:
-    type: string
-    description: MongoDB URI (external database)
-  mysql_uri:
-    type: string
-    description: |
-      Mysql URI with the following format:
-        mysql://<user>:<password>@<mysql_host>:<mysql_port>/<database>
-  image_pull_policy:
-    type: string
-    description: |
-      ImagePullPolicy configuration for the pod.
-      Possible values: always, ifnotpresent, never
-    default: always
-  debug_mode:
-    description: |
-      If true, debug mode is activated. It means that the service will not run,
-      and instead, the command for the container will be a `sleep infinity`.
-      Note: If enabled, security_context will be disabled.
-    type: boolean
-    default: false
-  debug_pubkey:
-    description: |
-      Public SSH key that will be injected to the application pod.
-    type: string
-  debug_pol_local_path:
-    description: |
-      Local full path to the POL project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  debug_common_local_path:
-    description: |
-      Local full path to the COMMON project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  security_context:
-    description: Enables the security context of the pods
-    type: boolean
-    default: false
diff --git a/installers/charm/pol/lib/charms/kafka_k8s/v0/kafka.py b/installers/charm/pol/lib/charms/kafka_k8s/v0/kafka.py
deleted file mode 100644 (file)
index 1baf9a8..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2022 Canonical Ltd.
-# See LICENSE file for licensing details.
-#
-# 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.
-
-"""Kafka library.
-
-This [library](https://juju.is/docs/sdk/libraries) implements both sides of the
-`kafka` [interface](https://juju.is/docs/sdk/relations).
-
-The *provider* side of this interface is implemented by the
-[kafka-k8s Charmed Operator](https://charmhub.io/kafka-k8s).
-
-Any Charmed Operator that *requires* Kafka for providing its
-service should implement the *requirer* side of this interface.
-
-In a nutshell using this library to implement a Charmed Operator *requiring*
-Kafka would look like
-
-```
-$ charmcraft fetch-lib charms.kafka_k8s.v0.kafka
-```
-
-`metadata.yaml`:
-
-```
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-```
-
-`src/charm.py`:
-
-```
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.charm import CharmBase
-
-
-class MyCharm(CharmBase):
-
-    on = KafkaEvents()
-
-    def __init__(self, *args):
-        super().__init__(*args)
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(
-            self.on.kafka_available,
-            self._on_kafka_available,
-        )
-        self.framework.observe(
-            self.on.kafka_broken,
-            self._on_kafka_broken,
-        )
-
-    def _on_kafka_available(self, event):
-        # Get Kafka host and port
-        host: str = self.kafka.host
-        port: int = self.kafka.port
-        # host => "kafka-k8s"
-        # port => 9092
-
-    def _on_kafka_broken(self, event):
-        # Stop service
-        # ...
-        self.unit.status = BlockedStatus("need kafka relation")
-```
-
-You can file bugs
-[here](https://github.com/charmed-osm/kafka-k8s-operator/issues)!
-"""
-
-from typing import Optional
-
-from ops.charm import CharmBase, CharmEvents
-from ops.framework import EventBase, EventSource, Object
-
-# The unique Charmhub library identifier, never change it
-from ops.model import Relation
-
-LIBID = "eacc8c85082347c9aae740e0220b8376"
-
-# Increment this major API version when introducing breaking changes
-LIBAPI = 0
-
-# Increment this PATCH version before using `charmcraft publish-lib` or reset
-# to 0 if you are raising the major API version
-LIBPATCH = 3
-
-
-KAFKA_HOST_APP_KEY = "host"
-KAFKA_PORT_APP_KEY = "port"
-
-
-class _KafkaAvailableEvent(EventBase):
-    """Event emitted when Kafka is available."""
-
-
-class _KafkaBrokenEvent(EventBase):
-    """Event emitted when Kafka relation is broken."""
-
-
-class KafkaEvents(CharmEvents):
-    """Kafka events.
-
-    This class defines the events that Kafka can emit.
-
-    Events:
-        kafka_available (_KafkaAvailableEvent)
-    """
-
-    kafka_available = EventSource(_KafkaAvailableEvent)
-    kafka_broken = EventSource(_KafkaBrokenEvent)
-
-
-class KafkaRequires(Object):
-    """Requires-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self.charm = charm
-        self._endpoint_name = endpoint_name
-
-        # Observe relation events
-        event_observe_mapping = {
-            charm.on[self._endpoint_name].relation_changed: self._on_relation_changed,
-            charm.on[self._endpoint_name].relation_broken: self._on_relation_broken,
-        }
-        for event, observer in event_observe_mapping.items():
-            self.framework.observe(event, observer)
-
-    def _on_relation_changed(self, event) -> None:
-        if event.relation.app and all(
-            key in event.relation.data[event.relation.app]
-            for key in (KAFKA_HOST_APP_KEY, KAFKA_PORT_APP_KEY)
-        ):
-            self.charm.on.kafka_available.emit()
-
-    def _on_relation_broken(self, _) -> None:
-        self.charm.on.kafka_broken.emit()
-
-    @property
-    def host(self) -> str:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            relation.data[relation.app].get(KAFKA_HOST_APP_KEY)
-            if relation and relation.app
-            else None
-        )
-
-    @property
-    def port(self) -> int:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            int(relation.data[relation.app].get(KAFKA_PORT_APP_KEY))
-            if relation and relation.app
-            else None
-        )
-
-
-class KafkaProvides(Object):
-    """Provides-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self._endpoint_name = endpoint_name
-
-    def set_host_info(self, host: str, port: int, relation: Optional[Relation] = None) -> None:
-        """Set Kafka host and port.
-
-        This function writes in the application data of the relation, therefore,
-        only the unit leader can call it.
-
-        Args:
-            host (str): Kafka hostname or IP address.
-            port (int): Kafka port.
-            relation (Optional[Relation]): Relation to update.
-                                           If not specified, all relations will be updated.
-
-        Raises:
-            Exception: if a non-leader unit calls this function.
-        """
-        if not self.model.unit.is_leader():
-            raise Exception("only the leader set host information.")
-
-        if relation:
-            self._update_relation_data(host, port, relation)
-            return
-
-        for relation in self.model.relations[self._endpoint_name]:
-            self._update_relation_data(host, port, relation)
-
-    def _update_relation_data(self, host: str, port: int, relation: Relation) -> None:
-        """Update data in relation if needed."""
-        relation.data[self.model.app][KAFKA_HOST_APP_KEY] = host
-        relation.data[self.model.app][KAFKA_PORT_APP_KEY] = str(port)
diff --git a/installers/charm/pol/metadata.yaml b/installers/charm/pol/metadata.yaml
deleted file mode 100644 (file)
index f9f6923..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-name: osm-pol
-summary: OSM Policy Module (POL)
-description: |
-  A CAAS charm to deploy OSM's Policy Module (POL).
-series:
-  - kubernetes
-tags:
-  - kubernetes
-  - osm
-  - pol
-min-juju-version: 2.8.0
-deployment:
-  type: stateless
-  service: cluster
-resources:
-  image:
-    type: oci-image
-    description: OSM docker image for POL
-    upstream-source: "opensourcemano/pol:latest"
-requires:
-  kafka:
-    interface: kafka
-  mongodb:
-    interface: mongodb
-  mysql:
-    interface: mysql
-    limit: 1
diff --git a/installers/charm/pol/requirements-test.txt b/installers/charm/pol/requirements-test.txt
deleted file mode 100644 (file)
index cf61dd4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-mock==4.0.3
diff --git a/installers/charm/pol/requirements.txt b/installers/charm/pol/requirements.txt
deleted file mode 100644 (file)
index 1a8928c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master
\ No newline at end of file
diff --git a/installers/charm/pol/src/charm.py b/installers/charm/pol/src/charm.py
deleted file mode 100755 (executable)
index 94f6ecb..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213
-
-
-import logging
-import re
-from typing import NoReturn, Optional
-
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.main import main
-from opslib.osm.charm import CharmedOsmBase, RelationsMissing
-from opslib.osm.interfaces.mongo import MongoClient
-from opslib.osm.interfaces.mysql import MysqlClient
-from opslib.osm.pod import (
-    ContainerV3Builder,
-    PodRestartPolicy,
-    PodSpecV3Builder,
-)
-from opslib.osm.validator import ModelValidator, validator
-
-
-logger = logging.getLogger(__name__)
-
-PORT = 9999
-DEFAULT_MYSQL_DATABASE = "pol"
-
-
-class ConfigModel(ModelValidator):
-    log_level: str
-    mongodb_uri: Optional[str]
-    mysql_uri: Optional[str]
-    image_pull_policy: str
-    debug_mode: bool
-    security_context: bool
-
-    @validator("log_level")
-    def validate_log_level(cls, v):
-        if v not in {"INFO", "DEBUG"}:
-            raise ValueError("value must be INFO or DEBUG")
-        return v
-
-    @validator("mongoddb_uri")
-    def validate_mongodb_uri(cls, v):
-        if v and not v.startswith("mongodb://"):
-            raise ValueError("mongodb_uri is not properly formed")
-        return v
-
-    @validator("mysql_uri")
-    def validate_mysql_uri(cls, v):
-        pattern = re.compile("^mysql:\/\/.*:.*@.*:\d+\/.*$")  # noqa: W605
-        if v and not pattern.search(v):
-            raise ValueError("mysql_uri is not properly formed")
-        return v
-
-    @validator("image_pull_policy")
-    def validate_image_pull_policy(cls, v):
-        values = {
-            "always": "Always",
-            "ifnotpresent": "IfNotPresent",
-            "never": "Never",
-        }
-        v = v.lower()
-        if v not in values.keys():
-            raise ValueError("value must be always, ifnotpresent or never")
-        return values[v]
-
-
-class PolCharm(CharmedOsmBase):
-    on = KafkaEvents()
-
-    def __init__(self, *args) -> NoReturn:
-        super().__init__(
-            *args,
-            oci_image="image",
-            vscode_workspace=VSCODE_WORKSPACE,
-        )
-        if self.config.get("debug_mode"):
-            self.enable_debug_mode(
-                pubkey=self.config.get("debug_pubkey"),
-                hostpaths={
-                    "POL": {
-                        "hostpath": self.config.get("debug_pol_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_policy_module",
-                    },
-                    "osm_common": {
-                        "hostpath": self.config.get("debug_common_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_common",
-                    },
-                },
-            )
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(self.on.kafka_available, self.configure_pod)
-        self.framework.observe(self.on.kafka_broken, self.configure_pod)
-
-        self.mongodb_client = MongoClient(self, "mongodb")
-        self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
-
-        self.mysql_client = MysqlClient(self, "mysql")
-        self.framework.observe(self.on["mysql"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mysql"].relation_broken, self.configure_pod)
-
-    def _check_missing_dependencies(self, config: ConfigModel):
-        missing_relations = []
-
-        if not self.kafka.host or not self.kafka.port:
-            missing_relations.append("kafka")
-        if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
-            missing_relations.append("mongodb")
-        if not config.mysql_uri and self.mysql_client.is_missing_data_in_unit():
-            missing_relations.append("mysql")
-        if missing_relations:
-            raise RelationsMissing(missing_relations)
-
-    def build_pod_spec(self, image_info):
-        # Validate config
-        config = ConfigModel(**dict(self.config))
-
-        if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
-            raise Exception("Mongodb data cannot be provided via config and relation")
-        if config.mysql_uri and not self.mysql_client.is_missing_data_in_unit():
-            raise Exception("Mysql data cannot be provided via config and relation")
-
-        # Check relations
-        self._check_missing_dependencies(config)
-
-        security_context_enabled = (
-            config.security_context if not config.debug_mode else False
-        )
-
-        # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder(
-            enable_security_context=security_context_enabled
-        )
-
-        # Add secrets to the pod
-        mongodb_secret_name = f"{self.app.name}-mongodb-secret"
-        pod_spec_builder.add_secret(
-            mongodb_secret_name,
-            {"uri": config.mongodb_uri or self.mongodb_client.connection_string},
-        )
-        mysql_secret_name = f"{self.app.name}-mysql-secret"
-        pod_spec_builder.add_secret(
-            mysql_secret_name,
-            {
-                "uri": config.mysql_uri
-                or self.mysql_client.get_root_uri(DEFAULT_MYSQL_DATABASE)
-            },
-        )
-
-        # Build Container
-        container_builder = ContainerV3Builder(
-            self.app.name,
-            image_info,
-            config.image_pull_policy,
-            run_as_non_root=security_context_enabled,
-        )
-        container_builder.add_port(name=self.app.name, port=PORT)
-        container_builder.add_envs(
-            {
-                # General configuration
-                "ALLOW_ANONYMOUS_LOGIN": "yes",
-                "OSMPOL_GLOBAL_LOGLEVEL": config.log_level,
-                # Kafka configuration
-                "OSMPOL_MESSAGE_DRIVER": "kafka",
-                "OSMPOL_MESSAGE_HOST": self.kafka.host,
-                "OSMPOL_MESSAGE_PORT": self.kafka.port,
-                # Database configuration
-                "OSMPOL_DATABASE_DRIVER": "mongo",
-            }
-        )
-        container_builder.add_secret_envs(
-            mongodb_secret_name, {"OSMPOL_DATABASE_URI": "uri"}
-        )
-        container_builder.add_secret_envs(
-            mysql_secret_name, {"OSMPOL_SQL_DATABASE_URI": "uri"}
-        )
-        container = container_builder.build()
-
-        # Add Pod restart policy
-        restart_policy = PodRestartPolicy()
-        restart_policy.add_secrets(
-            secret_names=(mongodb_secret_name, mysql_secret_name)
-        )
-        pod_spec_builder.set_restart_policy(restart_policy)
-
-        # Add container to pod spec
-        pod_spec_builder.add_container(container)
-
-        return pod_spec_builder.build()
-
-
-VSCODE_WORKSPACE = {
-    "folders": [
-        {"path": "/usr/lib/python3/dist-packages/osm_policy_module"},
-        {"path": "/usr/lib/python3/dist-packages/osm_common"},
-    ],
-    "settings": {},
-    "launch": {
-        "version": "0.2.0",
-        "configurations": [
-            {
-                "name": "POL",
-                "type": "python",
-                "request": "launch",
-                "module": "osm_policy_module.cmd.policy_module_agent",
-                "justMyCode": False,
-            }
-        ],
-    },
-}
-
-
-if __name__ == "__main__":
-    main(PolCharm)
diff --git a/installers/charm/pol/src/pod_spec.py b/installers/charm/pol/src/pod_spec.py
deleted file mode 100644 (file)
index 5ad4217..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import logging
-from typing import Any, Dict, List, NoReturn
-
-logger = logging.getLogger(__name__)
-
-
-def _validate_data(
-    config_data: Dict[str, Any], relation_data: Dict[str, Any]
-) -> NoReturn:
-    """Validate input data.
-
-    Args:
-        config_data (Dict[str, Any]): configuration data.
-        relation_data (Dict[str, Any]): relation data.
-    """
-    config_validators = {
-        "log_level": lambda value, _: (
-            isinstance(value, str) and value in ("INFO", "DEBUG")
-        ),
-    }
-    relation_validators = {
-        "message_host": lambda value, _: isinstance(value, str) and len(value) > 0,
-        "message_port": lambda value, _: isinstance(value, int) and value > 0,
-        "database_uri": lambda value, _: (
-            isinstance(value, str) and value.startswith("mongodb://")
-        ),
-    }
-    problems = []
-
-    for key, validator in config_validators.items():
-        valid = validator(config_data.get(key), config_data)
-
-        if not valid:
-            problems.append(key)
-
-    for key, validator in relation_validators.items():
-        valid = validator(relation_data.get(key), relation_data)
-
-        if not valid:
-            problems.append(key)
-
-    if len(problems) > 0:
-        raise ValueError("Errors found in: {}".format(", ".join(problems)))
-
-
-def _make_pod_ports(port: int) -> List[Dict[str, Any]]:
-    """Generate pod ports details.
-
-    Args:
-        port (int): port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod port details.
-    """
-    return [{"name": "pol", "containerPort": port, "protocol": "TCP"}]
-
-
-def _make_pod_envconfig(
-    config: Dict[str, Any], relation_state: Dict[str, Any]
-) -> Dict[str, Any]:
-    """Generate pod environment configuration.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-        relation_state (Dict[str, Any]): relation state information.
-
-    Returns:
-        Dict[str, Any]: pod environment configuration.
-    """
-    envconfig = {
-        # General configuration
-        "ALLOW_ANONYMOUS_LOGIN": "yes",
-        "OSMPOL_GLOBAL_LOGLEVEL": config["log_level"],
-        # Kafka configuration
-        "OSMPOL_MESSAGE_HOST": relation_state["message_host"],
-        "OSMPOL_MESSAGE_DRIVER": "kafka",
-        "OSMPOL_MESSAGE_PORT": relation_state["message_port"],
-        # Database configuration
-        "OSMPOL_DATABASE_DRIVER": "mongo",
-        "OSMPOL_DATABASE_URI": relation_state["database_uri"],
-    }
-
-    return envconfig
-
-
-def _make_startup_probe() -> Dict[str, Any]:
-    """Generate startup probe.
-
-    Returns:
-        Dict[str, Any]: startup probe.
-    """
-    return {
-        "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-        "initialDelaySeconds": 60,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_readiness_probe() -> Dict[str, Any]:
-    """Generate readiness probe.
-
-    Returns:
-        Dict[str, Any]: readiness probe.
-    """
-    return {
-        "exec": {
-            "command": ["sh", "-c", "osm-pol-healthcheck || exit 1"],
-        },
-        "periodSeconds": 10,
-        "timeoutSeconds": 5,
-        "successThreshold": 1,
-        "failureThreshold": 3,
-    }
-
-
-def _make_liveness_probe() -> Dict[str, Any]:
-    """Generate liveness probe.
-
-    Returns:
-        Dict[str, Any]: liveness probe.
-    """
-    return {
-        "exec": {
-            "command": ["sh", "-c", "osm-pol-healthcheck || exit 1"],
-        },
-        "initialDelaySeconds": 45,
-        "periodSeconds": 10,
-        "timeoutSeconds": 5,
-        "successThreshold": 1,
-        "failureThreshold": 3,
-    }
-
-
-def make_pod_spec(
-    image_info: Dict[str, str],
-    config: Dict[str, Any],
-    relation_state: Dict[str, Any],
-    app_name: str = "pol",
-    port: int = 80,
-) -> Dict[str, Any]:
-    """Generate the pod spec information.
-
-    Args:
-        image_info (Dict[str, str]): Object provided by
-                                     OCIImageResource("image").fetch().
-        config (Dict[str, Any]): Configuration information.
-        relation_state (Dict[str, Any]): Relation state information.
-        app_name (str, optional): Application name. Defaults to "pol".
-        port (int, optional): Port for the container. Defaults to 80.
-
-    Returns:
-        Dict[str, Any]: Pod spec dictionary for the charm.
-    """
-    if not image_info:
-        return None
-
-    _validate_data(config, relation_state)
-
-    ports = _make_pod_ports(port)
-    env_config = _make_pod_envconfig(config, relation_state)
-
-    return {
-        "version": 3,
-        "containers": [
-            {
-                "name": app_name,
-                "imageDetails": image_info,
-                "imagePullPolicy": "Always",
-                "ports": ports,
-                "envConfig": env_config,
-            }
-        ],
-        "kubernetesResources": {
-            "ingressResources": [],
-        },
-    }
diff --git a/installers/charm/pol/tests/__init__.py b/installers/charm/pol/tests/__init__.py
deleted file mode 100644 (file)
index 446d5ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-"""Init mocking for unit tests."""
-
-import sys
-
-
-import mock
-
-
-class OCIImageResourceErrorMock(Exception):
-    pass
-
-
-sys.path.append("src")
-
-oci_image = mock.MagicMock()
-oci_image.OCIImageResourceError = OCIImageResourceErrorMock
-sys.modules["oci_image"] = oci_image
-sys.modules["oci_image"].OCIImageResource().fetch.return_value = {}
diff --git a/installers/charm/pol/tests/test_charm.py b/installers/charm/pol/tests/test_charm.py
deleted file mode 100644 (file)
index 6cf435d..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import sys
-from typing import NoReturn
-import unittest
-
-from charm import PolCharm
-from ops.model import ActiveStatus, BlockedStatus
-from ops.testing import Harness
-
-
-class TestCharm(unittest.TestCase):
-    """Pol Charm unit tests."""
-
-    def setUp(self) -> NoReturn:
-        """Test setup"""
-        self.image_info = sys.modules["oci_image"].OCIImageResource().fetch()
-        self.harness = Harness(PolCharm)
-        self.harness.set_leader(is_leader=True)
-        self.harness.begin()
-        self.config = {
-            "log_level": "INFO",
-            "mongodb_uri": "",
-        }
-        self.harness.update_config(self.config)
-
-    def test_config_changed_no_relations(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["mongodb", "kafka"]
-            )
-        )
-
-    def test_config_changed_non_leader(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-        self.harness.set_leader(is_leader=False)
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-    def test_with_relations_and_mongodb_config(
-        self,
-    ) -> NoReturn:
-        "Test with relations and mongodb config (internal)"
-        self.initialize_mysql_relation()
-        self.initialize_kafka_relation()
-        self.initialize_mongo_config()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations(
-        self,
-    ) -> NoReturn:
-        "Test with relations (internal)"
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_mysql_relation()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_exception_mongodb_relation_and_config(
-        self,
-    ) -> NoReturn:
-        "Test with relation and config for Mongodb. Must fail"
-        self.initialize_mongo_relation()
-        self.initialize_mongo_config()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_mysql_config_success(self):
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_mysql_config()
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_mysql_config_wrong_value(self):
-        self.initialize_kafka_relation()
-        self.initialize_mongo_relation()
-        self.initialize_mysql_config(uri="wrong_uri")
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertIn(
-            "mysql_uri is not properly formed",
-            self.harness.charm.unit.status.message,
-        )
-
-    def test_mysql_config_and_relation(self):
-        self.initialize_mysql_relation()
-        self.initialize_mysql_config()
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        # import pdb; pdb.set_trace()
-        self.assertIn(
-            "Mysql data cannot be provided via config and relation",
-            self.harness.charm.unit.status.message,
-        )
-
-    def initialize_kafka_relation(self):
-        kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-        self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-        self.harness.update_relation_data(
-            kafka_relation_id, "kafka", {"host": "kafka", "port": 9092}
-        )
-
-    def initialize_mongo_config(self):
-        self.harness.update_config({"mongodb_uri": "mongodb://mongo:27017"})
-
-    def initialize_mongo_relation(self):
-        mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-        self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mongodb/0",
-            {"connection_string": "mongodb://mongo:27017"},
-        )
-
-    def initialize_mysql_config(self, uri=None):
-        self.harness.update_config(
-            {"mysql_uri": uri or "mysql://user:pass@mysql-host:3306/database"}
-        )
-
-    def initialize_mysql_relation(self):
-        mongodb_relation_id = self.harness.add_relation("mysql", "mysql")
-        self.harness.add_relation_unit(mongodb_relation_id, "mysql/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mysql/0",
-            {
-                "user": "user",
-                "password": "pass",
-                "host": "host",
-                "port": "1234",
-                "database": "pol",
-                "root_password": "root_password",
-            },
-        )
-
-
-if __name__ == "__main__":
-    unittest.main()
-
-
-# class TestCharm(unittest.TestCase):
-#     """POL Charm unit tests."""
-
-#     def setUp(self) -> NoReturn:
-#         """Test setup"""
-#         self.harness = Harness(PolCharm)
-#         self.harness.set_leader(is_leader=True)
-#         self.harness.begin()
-
-#     def test_on_start_without_relations(self) -> NoReturn:
-#         """Test installation without any relation."""
-#         self.harness.charm.on.start.emit()
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_start_with_relations(self) -> NoReturn:
-#         """Test deployment without keystone."""
-#         expected_result = {
-#             "version": 3,
-#             "containers": [
-#                 {
-#                     "name": "pol",
-#                     "imageDetails": self.harness.charm.image.fetch(),
-#                     "imagePullPolicy": "Always",
-#                     "ports": [
-#                         {
-#                             "name": "pol",
-#                             "containerPort": 80,
-#                             "protocol": "TCP",
-#                         }
-#                     ],
-#                     "envConfig": {
-#                         "ALLOW_ANONYMOUS_LOGIN": "yes",
-#                         "OSMPOL_GLOBAL_LOGLEVEL": "INFO",
-#                         "OSMPOL_MESSAGE_HOST": "kafka",
-#                         "OSMPOL_MESSAGE_DRIVER": "kafka",
-#                         "OSMPOL_MESSAGE_PORT": 9092,
-#                         "OSMPOL_DATABASE_DRIVER": "mongo",
-#                         "OSMPOL_DATABASE_URI": "mongodb://mongo:27017",
-#                     },
-#                 }
-#             ],
-#             "kubernetesResources": {"ingressResources": []},
-#         }
-
-#         self.harness.charm.on.start.emit()
-
-#         # Check if kafka datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.message_host)
-#         self.assertIsNone(self.harness.charm.state.message_port)
-
-#         # Check if mongodb datastore is initialized
-#         self.assertIsNone(self.harness.charm.state.database_uri)
-
-#         # Initializing the kafka relation
-#         kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             kafka_relation_id, "kafka/0", {"host": "kafka", "port": 9092}
-#         )
-
-#         # Initializing the mongo relation
-#         mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             mongodb_relation_id,
-#             "mongodb/0",
-#             {"connection_string": "mongodb://mongo:27017"},
-#         )
-
-#         # Checking if kafka data is stored
-#         self.assertEqual(self.harness.charm.state.message_host, "kafka")
-#         self.assertEqual(self.harness.charm.state.message_port, 9092)
-
-#         # Checking if mongodb data is stored
-#         self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
-
-#         # Verifying status
-#         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         pod_spec, _ = self.harness.get_pod_spec()
-
-#         self.assertDictEqual(expected_result, pod_spec)
-
-#     def test_on_kafka_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if kafka relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.message_host)
-#         self.assertIsNone(self.harness.charm.state.message_port)
-
-#         relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             relation_id, "kafka/0", {"host": "kafka", "port": 9092}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.message_host, "kafka")
-#         self.assertEqual(self.harness.charm.state.message_port, 9092)
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertNotIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relation"))
-
-#     def test_on_mongodb_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if mongodb relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         self.assertIsNone(self.harness.charm.state.database_uri)
-
-#         relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             relation_id, "mongodb/0", {"connection_string": "mongodb://mongo:27017"}
-#         )
-
-#         self.assertEqual(self.harness.charm.state.database_uri, "mongodb://mongo:27017")
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertNotIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relation"))
-
-
-# if __name__ == "__main__":
-#     unittest.main()
diff --git a/installers/charm/pol/tests/test_pod_spec.py b/installers/charm/pol/tests/test_pod_spec.py
deleted file mode 100644 (file)
index eb5f5cf..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-from typing import NoReturn
-import unittest
-
-import pod_spec
-
-
-class TestPodSpec(unittest.TestCase):
-    """Pod spec unit tests."""
-
-    def test_make_pod_ports(self) -> NoReturn:
-        """Testing make pod ports."""
-        port = 80
-
-        expected_result = [
-            {
-                "name": "pol",
-                "containerPort": port,
-                "protocol": "TCP",
-            }
-        ]
-
-        pod_ports = pod_spec._make_pod_ports(port)
-
-        self.assertListEqual(expected_result, pod_ports)
-
-    def test_make_pod_envconfig(self) -> NoReturn:
-        """Teting make pod envconfig."""
-        config = {
-            "log_level": "INFO",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-        }
-
-        expected_result = {
-            "ALLOW_ANONYMOUS_LOGIN": "yes",
-            "OSMPOL_GLOBAL_LOGLEVEL": config["log_level"],
-            "OSMPOL_MESSAGE_HOST": relation_state["message_host"],
-            "OSMPOL_MESSAGE_DRIVER": "kafka",
-            "OSMPOL_MESSAGE_PORT": relation_state["message_port"],
-            "OSMPOL_DATABASE_DRIVER": "mongo",
-            "OSMPOL_DATABASE_URI": relation_state["database_uri"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_startup_probe(self) -> NoReturn:
-        """Testing make startup probe."""
-        expected_result = {
-            "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-            "initialDelaySeconds": 60,
-            "timeoutSeconds": 5,
-        }
-
-        startup_probe = pod_spec._make_startup_probe()
-
-        self.assertDictEqual(expected_result, startup_probe)
-
-    def test_make_readiness_probe(self) -> NoReturn:
-        """Testing make readiness probe."""
-        expected_result = {
-            "exec": {
-                "command": ["sh", "-c", "osm-pol-healthcheck || exit 1"],
-            },
-            "periodSeconds": 10,
-            "timeoutSeconds": 5,
-            "successThreshold": 1,
-            "failureThreshold": 3,
-        }
-
-        readiness_probe = pod_spec._make_readiness_probe()
-
-        self.assertDictEqual(expected_result, readiness_probe)
-
-    def test_make_liveness_probe(self) -> NoReturn:
-        """Testing make liveness probe."""
-        expected_result = {
-            "exec": {
-                "command": ["sh", "-c", "osm-pol-healthcheck || exit 1"],
-            },
-            "initialDelaySeconds": 45,
-            "periodSeconds": 10,
-            "timeoutSeconds": 5,
-            "successThreshold": 1,
-            "failureThreshold": 3,
-        }
-
-        liveness_probe = pod_spec._make_liveness_probe()
-
-        self.assertDictEqual(expected_result, liveness_probe)
-
-    def test_make_pod_spec(self) -> NoReturn:
-        """Testing make pod spec."""
-        image_info = {"upstream-source": "opensourcemano/pol:8"}
-        config = {
-            "log_level": "INFO",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-        }
-        app_name = "pol"
-        port = 80
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": app_name,
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "ALLOW_ANONYMOUS_LOGIN": "yes",
-                        "OSMPOL_GLOBAL_LOGLEVEL": config["log_level"],
-                        "OSMPOL_MESSAGE_HOST": relation_state["message_host"],
-                        "OSMPOL_MESSAGE_DRIVER": "kafka",
-                        "OSMPOL_MESSAGE_PORT": relation_state["message_port"],
-                        "OSMPOL_DATABASE_DRIVER": "mongo",
-                        "OSMPOL_DATABASE_URI": relation_state["database_uri"],
-                    },
-                }
-            ],
-            "kubernetesResources": {"ingressResources": []},
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-    def test_make_pod_spec_without_image_info(self) -> NoReturn:
-        """Testing make pod spec without image_info."""
-        image_info = None
-        config = {
-            "log_level": "INFO",
-        }
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-        }
-        app_name = "pol"
-        port = 80
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertIsNone(spec)
-
-    def test_make_pod_spec_without_config(self) -> NoReturn:
-        """Testing make pod spec without config."""
-        image_info = {"upstream-source": "opensourcemano/pol:8"}
-        config = {}
-        relation_state = {
-            "message_host": "kafka",
-            "message_port": 9090,
-            "database_uri": "mongodb://mongo",
-        }
-        app_name = "pol"
-        port = 80
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-    def test_make_pod_spec_without_relation_state(self) -> NoReturn:
-        """Testing make pod spec without relation_state."""
-        image_info = {"upstream-source": "opensourcemano/pol:8"}
-        config = {
-            "log_level": "INFO",
-        }
-        relation_state = {}
-        app_name = "pol"
-        port = 80
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/pol/tox.ini b/installers/charm/pol/tox.ini
deleted file mode 100644 (file)
index f3c9144..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-#######################################################################################
-
-[tox]
-envlist = black, cover, flake8, pylint, yamllint, safety
-skipsdist = true
-
-[tox:jenkins]
-toxworkdir = /tmp/.tox
-
-[testenv]
-basepython = python3.8
-setenv =
-  VIRTUAL_ENV={envdir}
-  PYTHONPATH = {toxinidir}:{toxinidir}/lib:{toxinidir}/src
-  PYTHONDONTWRITEBYTECODE = 1
-deps =  -r{toxinidir}/requirements.txt
-
-
-#######################################################################################
-[testenv:black]
-deps = black
-commands =
-        black --check --diff src/ tests/
-
-
-#######################################################################################
-[testenv:cover]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        coverage
-        nose2
-commands =
-        sh -c 'rm -f nosetests.xml'
-        coverage erase
-        nose2 -C --coverage src
-        coverage report --omit='*tests*'
-        coverage html -d ./cover --omit='*tests*'
-        coverage xml -o coverage.xml --omit=*tests*
-whitelist_externals = sh
-
-
-#######################################################################################
-[testenv:flake8]
-deps =  flake8
-        flake8-import-order
-commands =
-        flake8 src/ tests/
-
-
-#######################################################################################
-[testenv:pylint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        pylint==2.10.2
-commands =
-    pylint -E src/ tests/
-
-
-#######################################################################################
-[testenv:safety]
-setenv =
-        LC_ALL=C.UTF-8
-        LANG=C.UTF-8
-deps =  {[testenv]deps}
-        safety
-commands =
-        - safety check --full-report
-
-
-#######################################################################################
-[testenv:yamllint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        yamllint
-commands = yamllint .
-
-#######################################################################################
-[testenv:build]
-passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
-whitelist_externals =
-  charmcraft
-  sh
-commands =
-  charmcraft pack
-  sh -c 'ubuntu_version=20.04; \
-        architectures="amd64-aarch64-arm64"; \
-        charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \
-        mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm'
-
-#######################################################################################
-[flake8]
-ignore =
-        W291,
-        W293,
-        W503,
-        E123,
-        E125,
-        E226,
-        E241,
-exclude =
-        .git,
-        __pycache__,
-        .tox,
-max-line-length = 120
-show-source = True
-builtins = _
-max-complexity = 10
-import-order-style = google
diff --git a/installers/charm/release_edge.sh b/installers/charm/release_edge.sh
deleted file mode 100755 (executable)
index 67d0b31..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-set -eux
-
-channel=edge
-tag=testing-daily
-
-# 1. Build charms
-./build.sh
-
-
-# New charms (with resources)
-charms="ng-ui nbi pla keystone ro lcm mon pol"
-for charm in $charms; do
-    echo "Releasing $charm charm"
-    cs_revision=$(charm push $charm/$charm.charm cs:~charmed-osm/$charm | tail -n +1 | head -1 | awk '{print $2}')
-    resource_revision=$(charm attach $cs_revision image=external::opensourcemano/$charm:$tag | tail -n +1 | sed 's/[^0-9]*//g')
-    image_revision_num=$(echo $resource_revision  | awk '{print $NF}')
-    resources_string="--resource image-$image_revision_num"
-    charm release --channel $channel $cs_revision $resources_string
-    echo "$charm charm released!"
-done
-
-charms="mongodb-exporter kafka-exporter mysqld-exporter"
-for charm in $charms; do
-    echo "Releasing $charm charm"
-    cs_revision=$(charm push $charm/$charm.charm cs:~charmed-osm/$charm | tail -n +1 | head -1 | awk '{print $2}')
-    resource_revision=$(charm attach $cs_revision image=external::bitnami/$charm:latest | tail -n +1 | sed 's/[^0-9]*//g')
-    image_revision_num=$(echo $resource_revision  | awk '{print $NF}')
-    resources_string="--resource image-$image_revision_num"
-    charm release --channel $channel $cs_revision $resources_string
-    echo "$charm charm released!"
-done
-
-charm="prometheus"
-echo "Releasing $charm charm"
-cs_revision=$(charm push $charm/$charm.charm cs:~charmed-osm/$charm | tail -n +1 | head -1 | awk '{print $2}')
-resource_revision=$(charm attach $cs_revision image=external::ubuntu/$charm:latest | tail -n +1 | sed 's/[^0-9]*//g')
-image_revision_num=$(echo $resource_revision  | awk '{print $NF}')
-backup_resource_revision=$(charm attach $cs_revision backup-image=external::ed1000/prometheus-backup:latest | tail -n +1 | sed 's/[^0-9]*//g')
-backup_image_revision_num=$(echo $backup_resource_revision  | awk '{print $NF}')
-resources_string="--resource image-$image_revision_num --resource backup-image-$backup_image_revision_num"
-charm release --channel $channel $cs_revision $resources_string
-echo "$charm charm released!"
-
-
-charm="grafana"
-echo "Releasing $charm charm"
-cs_revision=$(charm push $charm/$charm.charm cs:~charmed-osm/$charm | tail -n +1 | head -1 | awk '{print $2}')
-resource_revision=$(charm attach $cs_revision image=external::ubuntu/$charm:latest | tail -n +1 | sed 's/[^0-9]*//g')
-image_revision_num=$(echo $resource_revision  | awk '{print $NF}')
-resources_string="--resource image-$image_revision_num"
-charm release --channel $channel $cs_revision $resources_string
-echo "$charm charm released!"
-
-
-charm="zookeeper"
-echo "Releasing $charm charm"
-cs_revision=$(charm push $charm/$charm.charm cs:~charmed-osm/$charm | tail -n +1 | head -1 | awk '{print $2}')
-resource_revision=$(charm attach $cs_revision image=external::rocks.canonical.com:443/k8s.gcr.io/kubernetes-zookeeper:1.0-3.4.10 | tail -n +1 | sed 's/[^0-9]*//g')
-image_revision_num=$(echo $resource_revision  | awk '{print $NF}')
-resources_string="--resource image-$image_revision_num"
-charm release --channel $channel $cs_revision $resources_string
-echo "$charm charm released!"
-
-
-charm="kafka"
-echo "Releasing $charm charm"
-cs_revision=$(charm push $charm/$charm.charm cs:~charmed-osm/$charm | tail -n +1 | head -1 | awk '{print $2}')
-resource_revision=$(charm attach $cs_revision image=external::rocks.canonical.com:443/wurstmeister/kafka:2.12-2.2.1 | tail -n +1 | sed 's/[^0-9]*//g')
-image_revision_num=$(echo $resource_revision  | awk '{print $NF}')
-resources_string="--resource image-$image_revision_num"
-charm release --channel $channel $cs_revision $resources_string
-echo "$charm charm released!"
-
-
-# 3. Grant permissions
-all_charms="ng-ui nbi pla keystone ro lcm mon pol grafana prometheus mongodb-exporter kafka-exporter mysqld-exporter zookeeper kafka"
-for charm in $all_charms; do
-    echo "Granting permission for $charm charm"
-    charm grant cs:~charmed-osm/$charm --channel $channel --acl read everyone
-done
diff --git a/installers/charm/ro/.gitignore b/installers/charm/ro/.gitignore
deleted file mode 100644 (file)
index 2885df2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.stestr
-cover
-release
\ No newline at end of file
diff --git a/installers/charm/ro/.jujuignore b/installers/charm/ro/.jujuignore
deleted file mode 100644 (file)
index 3ae3e7d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-venv
-.vscode
-build
-*.charm
-.coverage
-coverage.xml
-.gitignore
-.stestr
-cover
-release
-tests/
-requirements*
-tox.ini
diff --git a/installers/charm/ro/.yamllint.yaml b/installers/charm/ro/.yamllint.yaml
deleted file mode 100644 (file)
index d71fb69..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
----
-extends: default
-
-yaml-files:
-  - "*.yaml"
-  - "*.yml"
-  - ".yamllint"
-ignore: |
-  .tox
-  cover/
-  build/
-  venv
-  release/
diff --git a/installers/charm/ro/README.md b/installers/charm/ro/README.md
deleted file mode 100644 (file)
index 9cf4200..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<!-- Copyright 2020 Canonical Ltd.
-
-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.
-
-For those usages not covered by the Apache License, Version 2.0 please
-contact: legal@canonical.com
-
-To get in touch with the maintainers, please contact:
-osm-charmers@lists.launchpad.net -->
-
-# RO operator Charm for Kubernetes
-
-## Requirements
diff --git a/installers/charm/ro/charmcraft.yaml b/installers/charm/ro/charmcraft.yaml
deleted file mode 100644 (file)
index 0a285a9..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-type: charm
-bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: ["amd64"]
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-          - aarch64
-          - arm64
-parts:
-  charm:
-    build-packages: [git]
diff --git a/installers/charm/ro/config.yaml b/installers/charm/ro/config.yaml
deleted file mode 100644 (file)
index 31bf8cb..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-options:
-  enable_ng_ro:
-    description: Enable NG-RO
-    type: boolean
-    default: true
-  database_commonkey:
-    description: Database COMMON KEY
-    type: string
-    default: osm
-  mongodb_uri:
-    type: string
-    description: MongoDB URI (external database)
-  log_level:
-    description: "Log Level"
-    type: string
-    default: "INFO"
-  period_refresh_active:
-    type: int
-    description: |
-      Updates the VNF status from VIM for every given period of time seconds.
-      Values equal or greater than 60 is allowed.
-      Disable the updates from VIM by setting -1.
-      Example:
-        $ juju config ro period_refresh_active=-1
-        $ juju config ro period_refresh_active=100
-  mysql_host:
-    type: string
-    description: MySQL Host (external database)
-  mysql_port:
-    type: int
-    description: MySQL Port (external database)
-  mysql_user:
-    type: string
-    description: MySQL User (external database)
-  mysql_password:
-    type: string
-    description: MySQL Password (external database)
-  mysql_root_password:
-    type: string
-    description: MySQL Root Password (external database)
-  vim_database:
-    type: string
-    description: "The database name."
-    default: "mano_vim_db"
-  ro_database:
-    type: string
-    description: "The database name."
-    default: "mano_db"
-  openmano_tenant:
-    type: string
-    description: "Openmano Tenant"
-    default: "osm"
-  certificates:
-    type: string
-    description: |
-      comma-separated list of <name>:<content> certificates.
-      Where:
-        name: name of the file for the certificate
-        content: base64 content of the certificate
-      The path for the files is /certs.
-  image_pull_policy:
-    type: string
-    description: |
-      ImagePullPolicy configuration for the pod.
-      Possible values: always, ifnotpresent, never
-    default: always
-  debug_mode:
-    description: |
-      If true, debug mode is activated. It means that the service will not run,
-      and instead, the command for the container will be a `sleep infinity`.
-      Note: If enabled, security_context will be disabled.
-    type: boolean
-    default: false
-  debug_pubkey:
-    description: |
-      Public SSH key that will be injected to the application pod.
-    type: string
-  debug_ro_local_path:
-    description: |
-      Local full path to the RO project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  debug_common_local_path:
-    description: |
-      Local full path to the COMMON project.
-
-      The path will be mounted to the docker image,
-      which means changes during the debugging will be saved in your local path.
-    type: string
-  security_context:
-    description: Enables the security context of the pods
-    type: boolean
-    default: false
diff --git a/installers/charm/ro/lib/charms/kafka_k8s/v0/kafka.py b/installers/charm/ro/lib/charms/kafka_k8s/v0/kafka.py
deleted file mode 100644 (file)
index 1baf9a8..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2022 Canonical Ltd.
-# See LICENSE file for licensing details.
-#
-# 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.
-
-"""Kafka library.
-
-This [library](https://juju.is/docs/sdk/libraries) implements both sides of the
-`kafka` [interface](https://juju.is/docs/sdk/relations).
-
-The *provider* side of this interface is implemented by the
-[kafka-k8s Charmed Operator](https://charmhub.io/kafka-k8s).
-
-Any Charmed Operator that *requires* Kafka for providing its
-service should implement the *requirer* side of this interface.
-
-In a nutshell using this library to implement a Charmed Operator *requiring*
-Kafka would look like
-
-```
-$ charmcraft fetch-lib charms.kafka_k8s.v0.kafka
-```
-
-`metadata.yaml`:
-
-```
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-```
-
-`src/charm.py`:
-
-```
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.charm import CharmBase
-
-
-class MyCharm(CharmBase):
-
-    on = KafkaEvents()
-
-    def __init__(self, *args):
-        super().__init__(*args)
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(
-            self.on.kafka_available,
-            self._on_kafka_available,
-        )
-        self.framework.observe(
-            self.on.kafka_broken,
-            self._on_kafka_broken,
-        )
-
-    def _on_kafka_available(self, event):
-        # Get Kafka host and port
-        host: str = self.kafka.host
-        port: int = self.kafka.port
-        # host => "kafka-k8s"
-        # port => 9092
-
-    def _on_kafka_broken(self, event):
-        # Stop service
-        # ...
-        self.unit.status = BlockedStatus("need kafka relation")
-```
-
-You can file bugs
-[here](https://github.com/charmed-osm/kafka-k8s-operator/issues)!
-"""
-
-from typing import Optional
-
-from ops.charm import CharmBase, CharmEvents
-from ops.framework import EventBase, EventSource, Object
-
-# The unique Charmhub library identifier, never change it
-from ops.model import Relation
-
-LIBID = "eacc8c85082347c9aae740e0220b8376"
-
-# Increment this major API version when introducing breaking changes
-LIBAPI = 0
-
-# Increment this PATCH version before using `charmcraft publish-lib` or reset
-# to 0 if you are raising the major API version
-LIBPATCH = 3
-
-
-KAFKA_HOST_APP_KEY = "host"
-KAFKA_PORT_APP_KEY = "port"
-
-
-class _KafkaAvailableEvent(EventBase):
-    """Event emitted when Kafka is available."""
-
-
-class _KafkaBrokenEvent(EventBase):
-    """Event emitted when Kafka relation is broken."""
-
-
-class KafkaEvents(CharmEvents):
-    """Kafka events.
-
-    This class defines the events that Kafka can emit.
-
-    Events:
-        kafka_available (_KafkaAvailableEvent)
-    """
-
-    kafka_available = EventSource(_KafkaAvailableEvent)
-    kafka_broken = EventSource(_KafkaBrokenEvent)
-
-
-class KafkaRequires(Object):
-    """Requires-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self.charm = charm
-        self._endpoint_name = endpoint_name
-
-        # Observe relation events
-        event_observe_mapping = {
-            charm.on[self._endpoint_name].relation_changed: self._on_relation_changed,
-            charm.on[self._endpoint_name].relation_broken: self._on_relation_broken,
-        }
-        for event, observer in event_observe_mapping.items():
-            self.framework.observe(event, observer)
-
-    def _on_relation_changed(self, event) -> None:
-        if event.relation.app and all(
-            key in event.relation.data[event.relation.app]
-            for key in (KAFKA_HOST_APP_KEY, KAFKA_PORT_APP_KEY)
-        ):
-            self.charm.on.kafka_available.emit()
-
-    def _on_relation_broken(self, _) -> None:
-        self.charm.on.kafka_broken.emit()
-
-    @property
-    def host(self) -> str:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            relation.data[relation.app].get(KAFKA_HOST_APP_KEY)
-            if relation and relation.app
-            else None
-        )
-
-    @property
-    def port(self) -> int:
-        relation: Relation = self.model.get_relation(self._endpoint_name)
-        return (
-            int(relation.data[relation.app].get(KAFKA_PORT_APP_KEY))
-            if relation and relation.app
-            else None
-        )
-
-
-class KafkaProvides(Object):
-    """Provides-side of the Kafka relation."""
-
-    def __init__(self, charm: CharmBase, endpoint_name: str = "kafka") -> None:
-        super().__init__(charm, endpoint_name)
-        self._endpoint_name = endpoint_name
-
-    def set_host_info(self, host: str, port: int, relation: Optional[Relation] = None) -> None:
-        """Set Kafka host and port.
-
-        This function writes in the application data of the relation, therefore,
-        only the unit leader can call it.
-
-        Args:
-            host (str): Kafka hostname or IP address.
-            port (int): Kafka port.
-            relation (Optional[Relation]): Relation to update.
-                                           If not specified, all relations will be updated.
-
-        Raises:
-            Exception: if a non-leader unit calls this function.
-        """
-        if not self.model.unit.is_leader():
-            raise Exception("only the leader set host information.")
-
-        if relation:
-            self._update_relation_data(host, port, relation)
-            return
-
-        for relation in self.model.relations[self._endpoint_name]:
-            self._update_relation_data(host, port, relation)
-
-    def _update_relation_data(self, host: str, port: int, relation: Relation) -> None:
-        """Update data in relation if needed."""
-        relation.data[self.model.app][KAFKA_HOST_APP_KEY] = host
-        relation.data[self.model.app][KAFKA_PORT_APP_KEY] = str(port)
diff --git a/installers/charm/ro/metadata.yaml b/installers/charm/ro/metadata.yaml
deleted file mode 100644 (file)
index 6e82e8c..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-name: osm-ro
-summary: OSM Resource Orchestrator (RO)
-description: |
-  A CAAS charm to deploy OSM's Resource Orchestrator (RO).
-series:
-  - kubernetes
-tags:
-  - kubernetes
-  - osm
-  - ro
-min-juju-version: 2.8.0
-deployment:
-  type: stateless
-  service: cluster
-resources:
-  image:
-    type: oci-image
-    description: OSM docker image for RO
-    upstream-source: "opensourcemano/ro:8"
-provides:
-  ro:
-    interface: http
-requires:
-  kafka:
-    interface: kafka
-    limit: 1
-  mongodb:
-    interface: mongodb
-    limit: 1
-  mysql:
-    interface: mysql
-    limit: 1
diff --git a/installers/charm/ro/requirements-test.txt b/installers/charm/ro/requirements-test.txt
deleted file mode 100644 (file)
index cf61dd4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-mock==4.0.3
diff --git a/installers/charm/ro/requirements.txt b/installers/charm/ro/requirements.txt
deleted file mode 100644 (file)
index 1a8928c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master
\ No newline at end of file
diff --git a/installers/charm/ro/src/charm.py b/installers/charm/ro/src/charm.py
deleted file mode 100755 (executable)
index 028dc0a..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-# pylint: disable=E0213
-
-import base64
-import logging
-from typing import Dict, NoReturn, Optional
-
-from charms.kafka_k8s.v0.kafka import KafkaEvents, KafkaRequires
-from ops.main import main
-from opslib.osm.charm import CharmedOsmBase, RelationsMissing
-from opslib.osm.interfaces.mongo import MongoClient
-from opslib.osm.interfaces.mysql import MysqlClient
-from opslib.osm.pod import (
-    ContainerV3Builder,
-    FilesV3Builder,
-    PodRestartPolicy,
-    PodSpecV3Builder,
-)
-from opslib.osm.validator import ModelValidator, validator
-
-logger = logging.getLogger(__name__)
-
-PORT = 9090
-
-
-def _check_certificate_data(name: str, content: str):
-    if not name or not content:
-        raise ValueError("certificate name and content must be a non-empty string")
-
-
-def _extract_certificates(certs_config: str):
-    certificates = {}
-    if certs_config:
-        cert_list = certs_config.split(",")
-        for cert in cert_list:
-            name, content = cert.split(":")
-            _check_certificate_data(name, content)
-            certificates[name] = content
-    return certificates
-
-
-def decode(content: str):
-    return base64.b64decode(content.encode("utf-8")).decode("utf-8")
-
-
-class ConfigModel(ModelValidator):
-    enable_ng_ro: bool
-    database_commonkey: str
-    mongodb_uri: Optional[str]
-    log_level: str
-    mysql_host: Optional[str]
-    mysql_port: Optional[int]
-    mysql_user: Optional[str]
-    mysql_password: Optional[str]
-    mysql_root_password: Optional[str]
-    vim_database: str
-    ro_database: str
-    openmano_tenant: str
-    certificates: Optional[str]
-    image_pull_policy: str
-    debug_mode: bool
-    security_context: bool
-    period_refresh_active: Optional[int]
-
-    @validator("log_level")
-    def validate_log_level(cls, v):
-        if v not in {"INFO", "DEBUG"}:
-            raise ValueError("value must be INFO or DEBUG")
-        return v
-
-    @validator("certificates")
-    def validate_certificates(cls, v):
-        # Raises an exception if it cannot extract the certificates
-        _extract_certificates(v)
-        return v
-
-    @validator("mongodb_uri")
-    def validate_mongodb_uri(cls, v):
-        if v and not v.startswith("mongodb://"):
-            raise ValueError("mongodb_uri is not properly formed")
-        return v
-
-    @validator("mysql_port")
-    def validate_mysql_port(cls, v):
-        if v and (v <= 0 or v >= 65535):
-            raise ValueError("Mysql port out of range")
-        return v
-
-    @validator("image_pull_policy")
-    def validate_image_pull_policy(cls, v):
-        values = {
-            "always": "Always",
-            "ifnotpresent": "IfNotPresent",
-            "never": "Never",
-        }
-        v = v.lower()
-        if v not in values.keys():
-            raise ValueError("value must be always, ifnotpresent or never")
-        return values[v]
-
-    @property
-    def certificates_dict(cls):
-        return _extract_certificates(cls.certificates) if cls.certificates else {}
-
-    @validator("period_refresh_active")
-    def validate_vim_refresh_period(cls, v):
-        if v and v < 60 and v != -1:
-            raise ValueError(
-                "Refresh Period is too tight, insert >= 60 seconds or disable using -1"
-            )
-        return v
-
-
-class RoCharm(CharmedOsmBase):
-    """GrafanaCharm Charm."""
-
-    on = KafkaEvents()
-
-    def __init__(self, *args) -> NoReturn:
-        """Prometheus Charm constructor."""
-        super().__init__(
-            *args,
-            oci_image="image",
-            vscode_workspace=VSCODE_WORKSPACE,
-        )
-        if self.config.get("debug_mode"):
-            self.enable_debug_mode(
-                pubkey=self.config.get("debug_pubkey"),
-                hostpaths={
-                    "osm_common": {
-                        "hostpath": self.config.get("debug_common_local_path"),
-                        "container-path": "/usr/lib/python3/dist-packages/osm_common",
-                    },
-                    **_get_ro_host_paths(self.config.get("debug_ro_local_path")),
-                },
-            )
-        self.kafka = KafkaRequires(self)
-        self.framework.observe(self.on.kafka_available, self.configure_pod)
-        self.framework.observe(self.on.kafka_broken, self.configure_pod)
-
-        self.mysql_client = MysqlClient(self, "mysql")
-        self.framework.observe(self.on["mysql"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mysql"].relation_broken, self.configure_pod)
-
-        self.mongodb_client = MongoClient(self, "mongodb")
-        self.framework.observe(self.on["mongodb"].relation_changed, self.configure_pod)
-        self.framework.observe(self.on["mongodb"].relation_broken, self.configure_pod)
-
-        self.framework.observe(self.on["ro"].relation_joined, self._publish_ro_info)
-
-    def _publish_ro_info(self, event):
-        """Publishes RO information.
-
-        Args:
-            event (EventBase): RO relation event.
-        """
-        if self.unit.is_leader():
-            rel_data = {
-                "host": self.model.app.name,
-                "port": str(PORT),
-            }
-            for k, v in rel_data.items():
-                event.relation.data[self.app][k] = v
-
-    def _check_missing_dependencies(self, config: ConfigModel):
-        missing_relations = []
-
-        if config.enable_ng_ro:
-            if not self.kafka.host or not self.kafka.port:
-                missing_relations.append("kafka")
-            if not config.mongodb_uri and self.mongodb_client.is_missing_data_in_unit():
-                missing_relations.append("mongodb")
-        else:
-            if not config.mysql_host and self.mysql_client.is_missing_data_in_unit():
-                missing_relations.append("mysql")
-        if missing_relations:
-            raise RelationsMissing(missing_relations)
-
-    def _validate_mysql_config(self, config: ConfigModel):
-        invalid_values = []
-        if not config.mysql_user:
-            invalid_values.append("Mysql user is empty")
-        if not config.mysql_password:
-            invalid_values.append("Mysql password is empty")
-        if not config.mysql_root_password:
-            invalid_values.append("Mysql root password empty")
-
-        if invalid_values:
-            raise ValueError("Invalid values: " + ", ".join(invalid_values))
-
-    def _build_cert_files(
-        self,
-        config: ConfigModel,
-    ):
-        cert_files_builder = FilesV3Builder()
-        for name, content in config.certificates_dict.items():
-            cert_files_builder.add_file(name, decode(content), mode=0o600)
-        return cert_files_builder.build()
-
-    def build_pod_spec(self, image_info):
-        # Validate config
-        config = ConfigModel(**dict(self.config))
-
-        if config.enable_ng_ro:
-            if config.mongodb_uri and not self.mongodb_client.is_missing_data_in_unit():
-                raise Exception(
-                    "Mongodb data cannot be provided via config and relation"
-                )
-        else:
-            if config.mysql_host and not self.mysql_client.is_missing_data_in_unit():
-                raise Exception("Mysql data cannot be provided via config and relation")
-
-            if config.mysql_host:
-                self._validate_mysql_config(config)
-
-        # Check relations
-        self._check_missing_dependencies(config)
-
-        security_context_enabled = (
-            config.security_context if not config.debug_mode else False
-        )
-
-        # Create Builder for the PodSpec
-        pod_spec_builder = PodSpecV3Builder(
-            enable_security_context=security_context_enabled
-        )
-
-        # Build Container
-        container_builder = ContainerV3Builder(
-            self.app.name,
-            image_info,
-            config.image_pull_policy,
-            run_as_non_root=security_context_enabled,
-        )
-        certs_files = self._build_cert_files(config)
-
-        if certs_files:
-            container_builder.add_volume_config("certs", "/certs", certs_files)
-
-        container_builder.add_port(name=self.app.name, port=PORT)
-        container_builder.add_http_readiness_probe(
-            "/ro/" if config.enable_ng_ro else "/openmano/tenants",
-            PORT,
-            initial_delay_seconds=10,
-            period_seconds=10,
-            timeout_seconds=5,
-            failure_threshold=3,
-        )
-        container_builder.add_http_liveness_probe(
-            "/ro/" if config.enable_ng_ro else "/openmano/tenants",
-            PORT,
-            initial_delay_seconds=600,
-            period_seconds=10,
-            timeout_seconds=5,
-            failure_threshold=3,
-        )
-        container_builder.add_envs(
-            {
-                "OSMRO_LOG_LEVEL": config.log_level,
-            }
-        )
-        if config.period_refresh_active:
-            container_builder.add_envs(
-                {
-                    "OSMRO_PERIOD_REFRESH_ACTIVE": config.period_refresh_active,
-                }
-            )
-        if config.enable_ng_ro:
-            # Add secrets to the pod
-            mongodb_secret_name = f"{self.app.name}-mongodb-secret"
-            pod_spec_builder.add_secret(
-                mongodb_secret_name,
-                {
-                    "uri": config.mongodb_uri or self.mongodb_client.connection_string,
-                    "commonkey": config.database_commonkey,
-                },
-            )
-            container_builder.add_envs(
-                {
-                    "OSMRO_MESSAGE_DRIVER": "kafka",
-                    "OSMRO_MESSAGE_HOST": self.kafka.host,
-                    "OSMRO_MESSAGE_PORT": self.kafka.port,
-                    # MongoDB configuration
-                    "OSMRO_DATABASE_DRIVER": "mongo",
-                }
-            )
-            container_builder.add_secret_envs(
-                secret_name=mongodb_secret_name,
-                envs={
-                    "OSMRO_DATABASE_URI": "uri",
-                    "OSMRO_DATABASE_COMMONKEY": "commonkey",
-                },
-            )
-            restart_policy = PodRestartPolicy()
-            restart_policy.add_secrets(secret_names=(mongodb_secret_name,))
-            pod_spec_builder.set_restart_policy(restart_policy)
-
-        else:
-            container_builder.add_envs(
-                {
-                    "RO_DB_HOST": config.mysql_host or self.mysql_client.host,
-                    "RO_DB_OVIM_HOST": config.mysql_host or self.mysql_client.host,
-                    "RO_DB_PORT": config.mysql_port or self.mysql_client.port,
-                    "RO_DB_OVIM_PORT": config.mysql_port or self.mysql_client.port,
-                    "RO_DB_USER": config.mysql_user or self.mysql_client.user,
-                    "RO_DB_OVIM_USER": config.mysql_user or self.mysql_client.user,
-                    "RO_DB_PASSWORD": config.mysql_password
-                    or self.mysql_client.password,
-                    "RO_DB_OVIM_PASSWORD": config.mysql_password
-                    or self.mysql_client.password,
-                    "RO_DB_ROOT_PASSWORD": config.mysql_root_password
-                    or self.mysql_client.root_password,
-                    "RO_DB_OVIM_ROOT_PASSWORD": config.mysql_root_password
-                    or self.mysql_client.root_password,
-                    "RO_DB_NAME": config.ro_database,
-                    "RO_DB_OVIM_NAME": config.vim_database,
-                    "OPENMANO_TENANT": config.openmano_tenant,
-                }
-            )
-        container = container_builder.build()
-
-        # Add container to pod spec
-        pod_spec_builder.add_container(container)
-
-        return pod_spec_builder.build()
-
-
-VSCODE_WORKSPACE = {
-    "folders": [
-        {"path": "/usr/lib/python3/dist-packages/osm_ng_ro"},
-        {"path": "/usr/lib/python3/dist-packages/osm_common"},
-        {"path": "/usr/lib/python3/dist-packages/osm_ro_plugin"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_arista_cloudvision"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_dpb"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_dynpac"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_floodlightof"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_ietfl2vpn"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_juniper_contrail"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_odlof"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_onos_vpls"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rosdn_onosof"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rovim_aws"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rovim_azure"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rovim_gcp"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rovim_openstack"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rovim_openvim"},
-        {"path": "/usr/lib/python3/dist-packages/osm_rovim_vmware"},
-    ],
-    "launch": {
-        "configurations": [
-            {
-                "module": "osm_ng_ro.ro_main",
-                "name": "NG RO",
-                "request": "launch",
-                "type": "python",
-                "justMyCode": False,
-            }
-        ],
-        "version": "0.2.0",
-    },
-    "settings": {},
-}
-
-
-def _get_ro_host_paths(ro_host_path: str) -> Dict:
-    """Get RO host paths"""
-    return (
-        {
-            "NG-RO": {
-                "hostpath": f"{ro_host_path}/NG-RO",
-                "container-path": "/usr/lib/python3/dist-packages/osm_ng_ro",
-            },
-            "RO-plugin": {
-                "hostpath": f"{ro_host_path}/RO-plugin",
-                "container-path": "/usr/lib/python3/dist-packages/osm_ro_plugin",
-            },
-            "RO-SDN-arista_cloudvision": {
-                "hostpath": f"{ro_host_path}/RO-SDN-arista_cloudvision",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_arista_cloudvision",
-            },
-            "RO-SDN-dpb": {
-                "hostpath": f"{ro_host_path}/RO-SDN-dpb",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_dpb",
-            },
-            "RO-SDN-dynpac": {
-                "hostpath": f"{ro_host_path}/RO-SDN-dynpac",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_dynpac",
-            },
-            "RO-SDN-floodlight_openflow": {
-                "hostpath": f"{ro_host_path}/RO-SDN-floodlight_openflow",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_floodlightof",
-            },
-            "RO-SDN-ietfl2vpn": {
-                "hostpath": f"{ro_host_path}/RO-SDN-ietfl2vpn",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_ietfl2vpn",
-            },
-            "RO-SDN-juniper_contrail": {
-                "hostpath": f"{ro_host_path}/RO-SDN-juniper_contrail",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_juniper_contrail",
-            },
-            "RO-SDN-odl_openflow": {
-                "hostpath": f"{ro_host_path}/RO-SDN-odl_openflow",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_odlof",
-            },
-            "RO-SDN-onos_openflow": {
-                "hostpath": f"{ro_host_path}/RO-SDN-onos_openflow",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_onosof",
-            },
-            "RO-SDN-onos_vpls": {
-                "hostpath": f"{ro_host_path}/RO-SDN-onos_vpls",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rosdn_onos_vpls",
-            },
-            "RO-VIM-aws": {
-                "hostpath": f"{ro_host_path}/RO-VIM-aws",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rovim_aws",
-            },
-            "RO-VIM-azure": {
-                "hostpath": f"{ro_host_path}/RO-VIM-azure",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rovim_azure",
-            },
-            "RO-VIM-gcp": {
-                "hostpath": f"{ro_host_path}/RO-VIM-gcp",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rovim_gcp",
-            },
-            "RO-VIM-openstack": {
-                "hostpath": f"{ro_host_path}/RO-VIM-openstack",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rovim_openstack",
-            },
-            "RO-VIM-openvim": {
-                "hostpath": f"{ro_host_path}/RO-VIM-openvim",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rovim_openvim",
-            },
-            "RO-VIM-vmware": {
-                "hostpath": f"{ro_host_path}/RO-VIM-vmware",
-                "container-path": "/usr/lib/python3/dist-packages/osm_rovim_vmware",
-            },
-        }
-        if ro_host_path
-        else {}
-    )
-
-
-if __name__ == "__main__":
-    main(RoCharm)
diff --git a/installers/charm/ro/src/pod_spec.py b/installers/charm/ro/src/pod_spec.py
deleted file mode 100644 (file)
index 1beba17..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import logging
-from typing import Any, Dict, List, NoReturn
-
-logger = logging.getLogger(__name__)
-
-
-def _validate_data(
-    config_data: Dict[str, Any], relation_data: Dict[str, Any]
-) -> NoReturn:
-    """Validates passed information.
-
-    Args:
-        config_data (Dict[str, Any]): configuration information.
-        relation_data (Dict[str, Any]): relation information
-
-    Raises:
-        ValueError: when config and/or relation data is not valid.
-    """
-    config_validators = {
-        "enable_ng_ro": lambda value, _: isinstance(value, bool),
-        "database_commonkey": lambda value, values: (
-            isinstance(value, str) and len(value) > 0
-        )
-        if values.get("enable_ng_ro", True)
-        else True,
-        "log_level": lambda value, _: (
-            isinstance(value, str) and value in ("INFO", "DEBUG")
-        ),
-        "vim_database": lambda value, values: (
-            isinstance(value, str) and len(value) > 0
-        )
-        if not values.get("enable_ng_ro", True)
-        else True,
-        "ro_database": lambda value, values: (isinstance(value, str) and len(value) > 0)
-        if not values.get("enable_ng_ro", True)
-        else True,
-        "openmano_tenant": lambda value, values: (
-            isinstance(value, str) and len(value) > 0
-        )
-        if not values.get("enable_ng_ro", True)
-        else True,
-    }
-    relation_validators = {
-        "kafka_host": lambda value, _: (isinstance(value, str) and len(value) > 0)
-        if config_data.get("enable_ng_ro", True)
-        else True,
-        "kafka_port": lambda value, _: (isinstance(value, str) and len(value) > 0)
-        if config_data.get("enable_ng_ro", True)
-        else True,
-        "mongodb_connection_string": lambda value, _: (
-            isinstance(value, str) and value.startswith("mongodb://")
-        )
-        if config_data.get("enable_ng_ro", True)
-        else True,
-        "mysql_host": lambda value, _: (isinstance(value, str) and len(value) > 0)
-        if not config_data.get("enable_ng_ro", True)
-        else True,
-        "mysql_port": lambda value, _: (isinstance(value, int) and value > 0)
-        if not config_data.get("enable_ng_ro", True)
-        else True,
-        "mysql_user": lambda value, _: (isinstance(value, str) and len(value) > 0)
-        if not config_data.get("enable_ng_ro", True)
-        else True,
-        "mysql_password": lambda value, _: (isinstance(value, str) and len(value) > 0)
-        if not config_data.get("enable_ng_ro", True)
-        else True,
-        "mysql_root_password": lambda value, _: (
-            isinstance(value, str) and len(value) > 0
-        )
-        if not config_data.get("enable_ng_ro", True)
-        else True,
-    }
-    problems = []
-
-    for key, validator in config_validators.items():
-        valid = validator(config_data.get(key), config_data)
-
-        if not valid:
-            problems.append(key)
-
-    for key, validator in relation_validators.items():
-        valid = validator(relation_data.get(key), relation_data)
-
-        if not valid:
-            problems.append(key)
-
-    if len(problems) > 0:
-        raise ValueError("Errors found in: {}".format(", ".join(problems)))
-
-
-def _make_pod_ports(port: int) -> List[Dict[str, Any]]:
-    """Generate pod ports details.
-
-    Args:
-        port (int): port to expose.
-
-    Returns:
-        List[Dict[str, Any]]: pod port details.
-    """
-    return [{"name": "ro", "containerPort": port, "protocol": "TCP"}]
-
-
-def _make_pod_envconfig(
-    config: Dict[str, Any], relation_state: Dict[str, Any]
-) -> Dict[str, Any]:
-    """Generate pod environment configuration.
-
-    Args:
-        config (Dict[str, Any]): configuration information.
-        relation_state (Dict[str, Any]): relation state information.
-
-    Returns:
-        Dict[str, Any]: pod environment configuration.
-    """
-    envconfig = {
-        # General configuration
-        "OSMRO_LOG_LEVEL": config["log_level"],
-    }
-
-    if config.get("enable_ng_ro", True):
-        # Kafka configuration
-        envconfig["OSMRO_MESSAGE_DRIVER"] = "kafka"
-        envconfig["OSMRO_MESSAGE_HOST"] = relation_state["kafka_host"]
-        envconfig["OSMRO_MESSAGE_PORT"] = relation_state["kafka_port"]
-
-        # MongoDB configuration
-        envconfig["OSMRO_DATABASE_DRIVER"] = "mongo"
-        envconfig["OSMRO_DATABASE_URI"] = relation_state["mongodb_connection_string"]
-        envconfig["OSMRO_DATABASE_COMMONKEY"] = config["database_commonkey"]
-    else:
-        envconfig["RO_DB_HOST"] = relation_state["mysql_host"]
-        envconfig["RO_DB_OVIM_HOST"] = relation_state["mysql_host"]
-        envconfig["RO_DB_PORT"] = relation_state["mysql_port"]
-        envconfig["RO_DB_OVIM_PORT"] = relation_state["mysql_port"]
-        envconfig["RO_DB_USER"] = relation_state["mysql_user"]
-        envconfig["RO_DB_OVIM_USER"] = relation_state["mysql_user"]
-        envconfig["RO_DB_PASSWORD"] = relation_state["mysql_password"]
-        envconfig["RO_DB_OVIM_PASSWORD"] = relation_state["mysql_password"]
-        envconfig["RO_DB_ROOT_PASSWORD"] = relation_state["mysql_root_password"]
-        envconfig["RO_DB_OVIM_ROOT_PASSWORD"] = relation_state["mysql_root_password"]
-        envconfig["RO_DB_NAME"] = config["ro_database"]
-        envconfig["RO_DB_OVIM_NAME"] = config["vim_database"]
-        envconfig["OPENMANO_TENANT"] = config["openmano_tenant"]
-
-    return envconfig
-
-
-def _make_startup_probe() -> Dict[str, Any]:
-    """Generate startup probe.
-
-    Returns:
-        Dict[str, Any]: startup probe.
-    """
-    return {
-        "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-        "initialDelaySeconds": 60,
-        "timeoutSeconds": 5,
-    }
-
-
-def _make_readiness_probe(port: int) -> Dict[str, Any]:
-    """Generate readiness probe.
-
-    Args:
-        port (int): service port.
-
-    Returns:
-        Dict[str, Any]: readiness probe.
-    """
-    return {
-        "httpGet": {
-            "path": "/openmano/tenants",
-            "port": port,
-        },
-        "periodSeconds": 10,
-        "timeoutSeconds": 5,
-        "successThreshold": 1,
-        "failureThreshold": 3,
-    }
-
-
-def _make_liveness_probe(port: int) -> Dict[str, Any]:
-    """Generate liveness probe.
-
-    Args:
-        port (int): service port.
-
-    Returns:
-        Dict[str, Any]: liveness probe.
-    """
-    return {
-        "httpGet": {
-            "path": "/openmano/tenants",
-            "port": port,
-        },
-        "initialDelaySeconds": 600,
-        "periodSeconds": 10,
-        "timeoutSeconds": 5,
-        "successThreshold": 1,
-        "failureThreshold": 3,
-    }
-
-
-def make_pod_spec(
-    image_info: Dict[str, str],
-    config: Dict[str, Any],
-    relation_state: Dict[str, Any],
-    app_name: str = "ro",
-    port: int = 9090,
-) -> Dict[str, Any]:
-    """Generate the pod spec information.
-
-    Args:
-        image_info (Dict[str, str]): Object provided by
-                                     OCIImageResource("image").fetch().
-        config (Dict[str, Any]): Configuration information.
-        relation_state (Dict[str, Any]): Relation state information.
-        app_name (str, optional): Application name. Defaults to "ro".
-        port (int, optional): Port for the container. Defaults to 9090.
-
-    Returns:
-        Dict[str, Any]: Pod spec dictionary for the charm.
-    """
-    if not image_info:
-        return None
-
-    _validate_data(config, relation_state)
-
-    ports = _make_pod_ports(port)
-    env_config = _make_pod_envconfig(config, relation_state)
-    startup_probe = _make_startup_probe()
-    readiness_probe = _make_readiness_probe(port)
-    liveness_probe = _make_liveness_probe(port)
-
-    return {
-        "version": 3,
-        "containers": [
-            {
-                "name": app_name,
-                "imageDetails": image_info,
-                "imagePullPolicy": "Always",
-                "ports": ports,
-                "envConfig": env_config,
-                "kubernetes": {
-                    "startupProbe": startup_probe,
-                    "readinessProbe": readiness_probe,
-                    "livenessProbe": liveness_probe,
-                },
-            }
-        ],
-        "kubernetesResources": {
-            "ingressResources": [],
-        },
-    }
diff --git a/installers/charm/ro/tests/__init__.py b/installers/charm/ro/tests/__init__.py
deleted file mode 100644 (file)
index 446d5ce..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-"""Init mocking for unit tests."""
-
-import sys
-
-
-import mock
-
-
-class OCIImageResourceErrorMock(Exception):
-    pass
-
-
-sys.path.append("src")
-
-oci_image = mock.MagicMock()
-oci_image.OCIImageResourceError = OCIImageResourceErrorMock
-sys.modules["oci_image"] = oci_image
-sys.modules["oci_image"].OCIImageResource().fetch.return_value = {}
diff --git a/installers/charm/ro/tests/test_charm.py b/installers/charm/ro/tests/test_charm.py
deleted file mode 100644 (file)
index f18e768..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-import base64
-from typing import NoReturn
-import unittest
-
-from charm import RoCharm
-from ops.model import ActiveStatus, BlockedStatus
-from ops.testing import Harness
-
-
-def encode(content: str):
-    return base64.b64encode(content.encode("ascii")).decode("utf-8")
-
-
-certificate_pem = encode(
-    """
------BEGIN CERTIFICATE-----
-MIIDazCCAlOgAwIBAgIUf1b0s3UKtrxHXH2rge7UaQyfJAMwDQYJKoZIhvcNAQEL
-BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
-GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTAzMjIxNzEyMjdaFw0zMTAz
-MjAxNzEyMjdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
-HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQCgCfCBgYAN6ON0yHDXuW407rFtJVRf0u46Jrp0Dk7J
-kkSZ1e7Kq14r7yFHazEBWv78oOdwBocvWrd8leLuf3bYGcHR65hRy6A/fbYm5Aje
-cKpwlFwaqfR4BLelwJl79jZ2rJX738cCBVrIk1nAVdOxGrXV4MTWUaKR2c+uKKvc
-OKRT+5VqCeP4N5FWeATZ/KqGu8uV9E9WhFgwIZyStemLyLaDbn5PmAQ6S9oeR5jJ
-o2gEEp/lDKvsqOWs76KFumSKa9hQs5Dw2lj0mb1UoyYK1gYc4ubzVChJadv44AU8
-MYtIjlFn1X1P+RjaKZNUIAGXkoLwYn6SizF6y6LiuFS9AgMBAAGjUzBRMB0GA1Ud
-DgQWBBRl+/23CB+FXczeAZRQyYcfOdy9YDAfBgNVHSMEGDAWgBRl+/23CB+FXcze
-AZRQyYcfOdy9YDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAd
-dkeDym6lRN8kWFtfu3IyiLF8G8sn91qNbH3Yr4TuTBhgcjYyW6PgisSbrNgA9ysE
-GoaF7ohb8GeVfCsQdK23+NpAlj/+DZ3OnGcxwXj1RUAz4yr9kanV1yuEtr1q2xJI
-UaECWr8HZlwGBAKNTGx2EXT2/2aFzgULpDcxzTKD+MRpKpMUrWhf9ULvVrclvHWe
-POLYhobUFuBHuo6rt5Rcq16j67zCX9EVTlAE3o2OECIWByK22sXdeOidYMpTkl4q
-8FrOqjNsx5d+SBPJBv/pqtBm4bA47Vx1P8tbWOQ4bXS0UmXgwpeBOU/O/ot30+KS
-JnKEy+dYyvVBKg77sRHw
------END CERTIFICATE-----
-"""
-)
-
-
-class TestCharm(unittest.TestCase):
-    """Prometheus Charm unit tests."""
-
-    def setUp(self) -> NoReturn:
-        """Test setup"""
-        self.harness = Harness(RoCharm)
-        self.harness.set_leader(is_leader=True)
-        self.harness.begin()
-        self.config = {
-            "enable_ng_ro": True,
-            "database_commonkey": "commonkey",
-            "mongodb_uri": "",
-            "log_level": "INFO",
-            "vim_database": "db_name",
-            "ro_database": "ro_db_name",
-            "openmano_tenant": "mano",
-            "certificates": f"cert1:{certificate_pem}",
-        }
-        self.harness.update_config(self.config)
-
-    def test_config_changed_no_relations(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["mongodb", "kafka"]
-            )
-        )
-
-        # Disable ng-ro
-        self.harness.update_config({"enable_ng_ro": False})
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-        self.assertTrue(
-            all(
-                relation in self.harness.charm.unit.status.message
-                for relation in ["mysql"]
-            )
-        )
-
-    def test_config_changed_non_leader(
-        self,
-    ) -> NoReturn:
-        """Test ingress resources without HTTP."""
-        self.harness.set_leader(is_leader=False)
-        self.harness.charm.on.config_changed.emit()
-
-        # Assertions
-        self.assertIsInstance(self.harness.charm.unit.status, ActiveStatus)
-
-    def test_with_relations_and_mongodb_config_ng(
-        self,
-    ) -> NoReturn:
-        "Test with relations (ng-ro)"
-
-        # Initializing the kafka relation
-        kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-        self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-        self.harness.update_relation_data(
-            kafka_relation_id, "kafka", {"host": "kafka", "port": 9092}
-        )
-
-        # Initializing the mongodb config
-        self.harness.update_config({"mongodb_uri": "mongodb://mongo:27017"})
-
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_with_relations_ng(
-        self,
-    ) -> NoReturn:
-        "Test with relations (ng-ro)"
-
-        # Initializing the kafka relation
-        kafka_relation_id = self.harness.add_relation("kafka", "kafka")
-        self.harness.add_relation_unit(kafka_relation_id, "kafka/0")
-        self.harness.update_relation_data(
-            kafka_relation_id, "kafka", {"host": "kafka", "port": 9092}
-        )
-
-        # Initializing the mongo relation
-        mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-        self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mongodb/0",
-            {"connection_string": "mongodb://mongo:27017"},
-        )
-
-        # Verifying status
-        self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-    def test_ng_exception_mongodb_relation_and_config(
-        self,
-    ) -> NoReturn:
-        "Test NG-RO mongodb relation and config. Must fail"
-        # Initializing the mongo relation
-        mongodb_relation_id = self.harness.add_relation("mongodb", "mongodb")
-        self.harness.add_relation_unit(mongodb_relation_id, "mongodb/0")
-        self.harness.update_relation_data(
-            mongodb_relation_id,
-            "mongodb/0",
-            {"connection_string": "mongodb://mongo:27017"},
-        )
-
-        # Initializing the mongodb config
-        self.harness.update_config({"mongodb_uri": "mongodb://mongo:27017"})
-
-        # Verifying status
-        self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-
-if __name__ == "__main__":
-    unittest.main()
-
-# class TestCharm(unittest.TestCase):
-#     """RO Charm unit tests."""
-
-#     def setUp(self) -> NoReturn:
-#         """Test setup"""
-#         self.harness = Harness(RoCharm)
-#         self.harness.set_leader(is_leader=True)
-#         self.harness.begin()
-
-#     def test_on_start_without_relations_ng_ro(self) -> NoReturn:
-#         """Test installation without any relation."""
-#         self.harness.charm.on.start.emit()
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_on_start_without_relations_no_ng_ro(self) -> NoReturn:
-#         """Test installation without any relation."""
-#         self.harness.update_config({"enable_ng_ro": False})
-
-#         self.harness.charm.on.start.emit()
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("mysql", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relation"))
-
-#     def test_on_start_with_relations_ng_ro(self) -> NoReturn:
-#         """Test deployment with NG-RO."""
-#         expected_result = {
-#             "version": 3,
-#             "containers": [
-#                 {
-#                     "name": "ro",
-#                     "imageDetails": self.harness.charm.image.fetch(),
-#                     "imagePullPolicy": "Always",
-#                     "ports": [
-#                         {
-#                             "name": "ro",
-#                             "containerPort": 9090,
-#                             "protocol": "TCP",
-#                         }
-#                     ],
-#                     "envConfig": {
-#                         "OSMRO_LOG_LEVEL": "INFO",
-#                         "OSMRO_MESSAGE_DRIVER": "kafka",
-#                         "OSMRO_MESSAGE_HOST": "kafka",
-#                         "OSMRO_MESSAGE_PORT": "9090",
-#                         "OSMRO_DATABASE_DRIVER": "mongo",
-#                         "OSMRO_DATABASE_URI": "mongodb://mongo",
-#                         "OSMRO_DATABASE_COMMONKEY": "osm",
-#                     },
-#                     "kubernetes": {
-#                         "startupProbe": {
-#                             "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-#                             "initialDelaySeconds": 60,
-#                             "timeoutSeconds": 5,
-#                         },
-#                         "readinessProbe": {
-#                             "httpGet": {
-#                                 "path": "/openmano/tenants",
-#                                 "port": 9090,
-#                             },
-#                             "periodSeconds": 10,
-#                             "timeoutSeconds": 5,
-#                             "successThreshold": 1,
-#                             "failureThreshold": 3,
-#                         },
-#                         "livenessProbe": {
-#                             "httpGet": {
-#                                 "path": "/openmano/tenants",
-#                                 "port": 9090,
-#                             },
-#                             "initialDelaySeconds": 600,
-#                             "periodSeconds": 10,
-#                             "timeoutSeconds": 5,
-#                             "successThreshold": 1,
-#                             "failureThreshold": 3,
-#                         },
-#                     },
-#                 }
-#             ],
-#             "kubernetesResources": {"ingressResources": []},
-#         }
-
-#         self.harness.charm.on.start.emit()
-
-#         # Initializing the kafka relation
-#         relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             relation_id,
-#             "kafka/0",
-#             {
-#                 "host": "kafka",
-#                 "port": "9090",
-#             },
-#         )
-
-#         # Initializing the mongodb relation
-#         relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             relation_id,
-#             "mongodb/0",
-#             {
-#                 "connection_string": "mongodb://mongo",
-#             },
-#         )
-
-#         # Verifying status
-#         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         pod_spec, _ = self.harness.get_pod_spec()
-
-#         self.assertDictEqual(expected_result, pod_spec)
-
-#     def test_on_start_with_relations_no_ng_ro(self) -> NoReturn:
-#         """Test deployment with old RO."""
-#         self.harness.update_config({"enable_ng_ro": False})
-
-#         expected_result = {
-#             "version": 3,
-#             "containers": [
-#                 {
-#                     "name": "ro",
-#                     "imageDetails": self.harness.charm.image.fetch(),
-#                     "imagePullPolicy": "Always",
-#                     "ports": [
-#                         {
-#                             "name": "ro",
-#                             "containerPort": 9090,
-#                             "protocol": "TCP",
-#                         }
-#                     ],
-#                     "envConfig": {
-#                         "OSMRO_LOG_LEVEL": "INFO",
-#                         "RO_DB_HOST": "mysql",
-#                         "RO_DB_OVIM_HOST": "mysql",
-#                         "RO_DB_PORT": 3306,
-#                         "RO_DB_OVIM_PORT": 3306,
-#                         "RO_DB_USER": "mano",
-#                         "RO_DB_OVIM_USER": "mano",
-#                         "RO_DB_PASSWORD": "manopw",
-#                         "RO_DB_OVIM_PASSWORD": "manopw",
-#                         "RO_DB_ROOT_PASSWORD": "rootmanopw",
-#                         "RO_DB_OVIM_ROOT_PASSWORD": "rootmanopw",
-#                         "RO_DB_NAME": "mano_db",
-#                         "RO_DB_OVIM_NAME": "mano_vim_db",
-#                         "OPENMANO_TENANT": "osm",
-#                     },
-#                     "kubernetes": {
-#                         "startupProbe": {
-#                             "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-#                             "initialDelaySeconds": 60,
-#                             "timeoutSeconds": 5,
-#                         },
-#                         "readinessProbe": {
-#                             "httpGet": {
-#                                 "path": "/openmano/tenants",
-#                                 "port": 9090,
-#                             },
-#                             "periodSeconds": 10,
-#                             "timeoutSeconds": 5,
-#                             "successThreshold": 1,
-#                             "failureThreshold": 3,
-#                         },
-#                         "livenessProbe": {
-#                             "httpGet": {
-#                                 "path": "/openmano/tenants",
-#                                 "port": 9090,
-#                             },
-#                             "initialDelaySeconds": 600,
-#                             "periodSeconds": 10,
-#                             "timeoutSeconds": 5,
-#                             "successThreshold": 1,
-#                             "failureThreshold": 3,
-#                         },
-#                     },
-#                 }
-#             ],
-#             "kubernetesResources": {"ingressResources": []},
-#         }
-
-#         self.harness.charm.on.start.emit()
-
-#         # Initializing the mysql relation
-#         relation_id = self.harness.add_relation("mysql", "mysql")
-#         self.harness.add_relation_unit(relation_id, "mysql/0")
-#         self.harness.update_relation_data(
-#             relation_id,
-#             "mysql/0",
-#             {
-#                 "host": "mysql",
-#                 "port": 3306,
-#                 "user": "mano",
-#                 "password": "manopw",
-#                 "root_password": "rootmanopw",
-#             },
-#         )
-
-#         # Verifying status
-#         self.assertNotIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         pod_spec, _ = self.harness.get_pod_spec()
-
-#         self.assertDictEqual(expected_result, pod_spec)
-
-#     def test_on_kafka_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if kafka relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         relation_id = self.harness.add_relation("kafka", "kafka")
-#         self.harness.add_relation_unit(relation_id, "kafka/0")
-#         self.harness.update_relation_data(
-#             relation_id,
-#             "kafka/0",
-#             {
-#                 "host": "kafka",
-#                 "port": 9090,
-#             },
-#         )
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relation"))
-
-#     def test_on_mongodb_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if mongodb relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         relation_id = self.harness.add_relation("mongodb", "mongodb")
-#         self.harness.add_relation_unit(relation_id, "mongodb/0")
-#         self.harness.update_relation_data(
-#             relation_id,
-#             "mongodb/0",
-#             {
-#                 "connection_string": "mongodb://mongo",
-#             },
-#         )
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relation"))
-
-#     def test_on_mysql_unit_relation_changed(self) -> NoReturn:
-#         """Test to see if mysql relation is updated."""
-#         self.harness.charm.on.start.emit()
-
-#         relation_id = self.harness.add_relation("mysql", "mysql")
-#         self.harness.add_relation_unit(relation_id, "mysql/0")
-#         self.harness.update_relation_data(
-#             relation_id,
-#             "mysql/0",
-#             {
-#                 "host": "mysql",
-#                 "port": 3306,
-#                 "user": "mano",
-#                 "password": "manopw",
-#                 "root_password": "rootmanopw",
-#             },
-#         )
-
-#         # Verifying status
-#         self.assertIsInstance(self.harness.charm.unit.status, BlockedStatus)
-
-#         # Verifying status message
-#         self.assertGreater(len(self.harness.charm.unit.status.message), 0)
-#         self.assertTrue(
-#             self.harness.charm.unit.status.message.startswith("Waiting for ")
-#         )
-#         self.assertIn("kafka", self.harness.charm.unit.status.message)
-#         self.assertIn("mongodb", self.harness.charm.unit.status.message)
-#         self.assertTrue(self.harness.charm.unit.status.message.endswith(" relations"))
-
-#     def test_publish_ro_info(self) -> NoReturn:
-#         """Test to see if ro relation is updated."""
-#         expected_result = {
-#             "host": "ro",
-#             "port": "9090",
-#         }
-
-#         self.harness.charm.on.start.emit()
-
-#         relation_id = self.harness.add_relation("ro", "lcm")
-#         self.harness.add_relation_unit(relation_id, "lcm/0")
-#         relation_data = self.harness.get_relation_data(relation_id, "ro")
-
-#         self.assertDictEqual(expected_result, relation_data)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/ro/tests/test_pod_spec.py b/installers/charm/ro/tests/test_pod_spec.py
deleted file mode 100644 (file)
index e616242..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-
-from typing import NoReturn
-import unittest
-
-import pod_spec
-
-
-class TestPodSpec(unittest.TestCase):
-    """Pod spec unit tests."""
-
-    def test_make_pod_ports(self) -> NoReturn:
-        """Testing make pod ports."""
-        port = 9090
-
-        expected_result = [
-            {
-                "name": "ro",
-                "containerPort": port,
-                "protocol": "TCP",
-            }
-        ]
-
-        pod_ports = pod_spec._make_pod_ports(port)
-
-        self.assertListEqual(expected_result, pod_ports)
-
-    def test_make_pod_envconfig_ng_ro(self) -> NoReturn:
-        """Teting make pod envconfig."""
-        config = {
-            "enable_ng_ro": True,
-            "database_commonkey": "osm",
-            "log_level": "INFO",
-        }
-        relation_state = {
-            "kafka_host": "kafka",
-            "kafka_port": "9090",
-            "mongodb_connection_string": "mongodb://mongo",
-        }
-
-        expected_result = {
-            "OSMRO_LOG_LEVEL": config["log_level"],
-            "OSMRO_MESSAGE_DRIVER": "kafka",
-            "OSMRO_MESSAGE_HOST": relation_state["kafka_host"],
-            "OSMRO_MESSAGE_PORT": relation_state["kafka_port"],
-            "OSMRO_DATABASE_DRIVER": "mongo",
-            "OSMRO_DATABASE_URI": relation_state["mongodb_connection_string"],
-            "OSMRO_DATABASE_COMMONKEY": config["database_commonkey"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_pod_envconfig_no_ng_ro(self) -> NoReturn:
-        """Teting make pod envconfig."""
-        config = {
-            "log_level": "INFO",
-            "enable_ng_ro": False,
-            "vim_database": "mano_vim_db",
-            "ro_database": "mano_db",
-            "openmano_tenant": "osm",
-        }
-        relation_state = {
-            "mysql_host": "mysql",
-            "mysql_port": 3306,
-            "mysql_user": "mano",
-            "mysql_password": "manopw",
-            "mysql_root_password": "rootmanopw",
-        }
-
-        expected_result = {
-            "OSMRO_LOG_LEVEL": config["log_level"],
-            "RO_DB_HOST": relation_state["mysql_host"],
-            "RO_DB_OVIM_HOST": relation_state["mysql_host"],
-            "RO_DB_PORT": relation_state["mysql_port"],
-            "RO_DB_OVIM_PORT": relation_state["mysql_port"],
-            "RO_DB_USER": relation_state["mysql_user"],
-            "RO_DB_OVIM_USER": relation_state["mysql_user"],
-            "RO_DB_PASSWORD": relation_state["mysql_password"],
-            "RO_DB_OVIM_PASSWORD": relation_state["mysql_password"],
-            "RO_DB_ROOT_PASSWORD": relation_state["mysql_root_password"],
-            "RO_DB_OVIM_ROOT_PASSWORD": relation_state["mysql_root_password"],
-            "RO_DB_NAME": config["ro_database"],
-            "RO_DB_OVIM_NAME": config["vim_database"],
-            "OPENMANO_TENANT": config["openmano_tenant"],
-        }
-
-        pod_envconfig = pod_spec._make_pod_envconfig(config, relation_state)
-
-        self.assertDictEqual(expected_result, pod_envconfig)
-
-    def test_make_startup_probe(self) -> NoReturn:
-        """Testing make startup probe."""
-        expected_result = {
-            "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-            "initialDelaySeconds": 60,
-            "timeoutSeconds": 5,
-        }
-
-        startup_probe = pod_spec._make_startup_probe()
-
-        self.assertDictEqual(expected_result, startup_probe)
-
-    def test_make_readiness_probe(self) -> NoReturn:
-        """Testing make readiness probe."""
-        port = 9090
-
-        expected_result = {
-            "httpGet": {
-                "path": "/openmano/tenants",
-                "port": port,
-            },
-            "periodSeconds": 10,
-            "timeoutSeconds": 5,
-            "successThreshold": 1,
-            "failureThreshold": 3,
-        }
-
-        readiness_probe = pod_spec._make_readiness_probe(port)
-
-        self.assertDictEqual(expected_result, readiness_probe)
-
-    def test_make_liveness_probe(self) -> NoReturn:
-        """Testing make liveness probe."""
-        port = 9090
-
-        expected_result = {
-            "httpGet": {
-                "path": "/openmano/tenants",
-                "port": port,
-            },
-            "initialDelaySeconds": 600,
-            "periodSeconds": 10,
-            "timeoutSeconds": 5,
-            "successThreshold": 1,
-            "failureThreshold": 3,
-        }
-
-        liveness_probe = pod_spec._make_liveness_probe(port)
-
-        self.assertDictEqual(expected_result, liveness_probe)
-
-    def test_make_pod_spec_ng_ro(self) -> NoReturn:
-        """Testing make pod spec."""
-        image_info = {"upstream-source": "opensourcemano/ro:8"}
-        config = {
-            "database_commonkey": "osm",
-            "log_level": "INFO",
-            "enable_ng_ro": True,
-        }
-        relation_state = {
-            "kafka_host": "kafka",
-            "kafka_port": "9090",
-            "mongodb_connection_string": "mongodb://mongo",
-        }
-        app_name = "ro"
-        port = 9090
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": app_name,
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "OSMRO_LOG_LEVEL": config["log_level"],
-                        "OSMRO_MESSAGE_DRIVER": "kafka",
-                        "OSMRO_MESSAGE_HOST": relation_state["kafka_host"],
-                        "OSMRO_MESSAGE_PORT": relation_state["kafka_port"],
-                        "OSMRO_DATABASE_DRIVER": "mongo",
-                        "OSMRO_DATABASE_URI": relation_state[
-                            "mongodb_connection_string"
-                        ],
-                        "OSMRO_DATABASE_COMMONKEY": config["database_commonkey"],
-                    },
-                    "kubernetes": {
-                        "startupProbe": {
-                            "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-                            "initialDelaySeconds": 60,
-                            "timeoutSeconds": 5,
-                        },
-                        "readinessProbe": {
-                            "httpGet": {
-                                "path": "/openmano/tenants",
-                                "port": port,
-                            },
-                            "periodSeconds": 10,
-                            "timeoutSeconds": 5,
-                            "successThreshold": 1,
-                            "failureThreshold": 3,
-                        },
-                        "livenessProbe": {
-                            "httpGet": {
-                                "path": "/openmano/tenants",
-                                "port": port,
-                            },
-                            "initialDelaySeconds": 600,
-                            "periodSeconds": 10,
-                            "timeoutSeconds": 5,
-                            "successThreshold": 1,
-                            "failureThreshold": 3,
-                        },
-                    },
-                }
-            ],
-            "kubernetesResources": {"ingressResources": []},
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-    def test_make_pod_spec_no_ng_ro(self) -> NoReturn:
-        """Testing make pod spec."""
-        image_info = {"upstream-source": "opensourcemano/ro:8"}
-        config = {
-            "log_level": "INFO",
-            "enable_ng_ro": False,
-            "vim_database": "mano_vim_db",
-            "ro_database": "mano_db",
-            "openmano_tenant": "osm",
-        }
-        relation_state = {
-            "mysql_host": "mysql",
-            "mysql_port": 3306,
-            "mysql_user": "mano",
-            "mysql_password": "manopw",
-            "mysql_root_password": "rootmanopw",
-        }
-        app_name = "ro"
-        port = 9090
-
-        expected_result = {
-            "version": 3,
-            "containers": [
-                {
-                    "name": app_name,
-                    "imageDetails": image_info,
-                    "imagePullPolicy": "Always",
-                    "ports": [
-                        {
-                            "name": app_name,
-                            "containerPort": port,
-                            "protocol": "TCP",
-                        }
-                    ],
-                    "envConfig": {
-                        "OSMRO_LOG_LEVEL": config["log_level"],
-                        "RO_DB_HOST": relation_state["mysql_host"],
-                        "RO_DB_OVIM_HOST": relation_state["mysql_host"],
-                        "RO_DB_PORT": relation_state["mysql_port"],
-                        "RO_DB_OVIM_PORT": relation_state["mysql_port"],
-                        "RO_DB_USER": relation_state["mysql_user"],
-                        "RO_DB_OVIM_USER": relation_state["mysql_user"],
-                        "RO_DB_PASSWORD": relation_state["mysql_password"],
-                        "RO_DB_OVIM_PASSWORD": relation_state["mysql_password"],
-                        "RO_DB_ROOT_PASSWORD": relation_state["mysql_root_password"],
-                        "RO_DB_OVIM_ROOT_PASSWORD": relation_state[
-                            "mysql_root_password"
-                        ],
-                        "RO_DB_NAME": config["ro_database"],
-                        "RO_DB_OVIM_NAME": config["vim_database"],
-                        "OPENMANO_TENANT": config["openmano_tenant"],
-                    },
-                    "kubernetes": {
-                        "startupProbe": {
-                            "exec": {"command": ["/usr/bin/pgrep", "python3"]},
-                            "initialDelaySeconds": 60,
-                            "timeoutSeconds": 5,
-                        },
-                        "readinessProbe": {
-                            "httpGet": {
-                                "path": "/openmano/tenants",
-                                "port": port,
-                            },
-                            "periodSeconds": 10,
-                            "timeoutSeconds": 5,
-                            "successThreshold": 1,
-                            "failureThreshold": 3,
-                        },
-                        "livenessProbe": {
-                            "httpGet": {
-                                "path": "/openmano/tenants",
-                                "port": port,
-                            },
-                            "initialDelaySeconds": 600,
-                            "periodSeconds": 10,
-                            "timeoutSeconds": 5,
-                            "successThreshold": 1,
-                            "failureThreshold": 3,
-                        },
-                    },
-                }
-            ],
-            "kubernetesResources": {"ingressResources": []},
-        }
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertDictEqual(expected_result, spec)
-
-    def test_make_pod_spec_without_image_info(self) -> NoReturn:
-        """Testing make pod spec without image_info."""
-        image_info = None
-        config = {
-            "enable_ng_ro": True,
-            "database_commonkey": "osm",
-            "log_level": "INFO",
-        }
-        relation_state = {
-            "kafka_host": "kafka",
-            "kafka_port": 9090,
-            "mongodb_connection_string": "mongodb://mongo",
-        }
-        app_name = "ro"
-        port = 9090
-
-        spec = pod_spec.make_pod_spec(
-            image_info, config, relation_state, app_name, port
-        )
-
-        self.assertIsNone(spec)
-
-    def test_make_pod_spec_without_config(self) -> NoReturn:
-        """Testing make pod spec without config."""
-        image_info = {"upstream-source": "opensourcemano/ro:8"}
-        config = {}
-        relation_state = {
-            "kafka_host": "kafka",
-            "kafka_port": 9090,
-            "mongodb_connection_string": "mongodb://mongo",
-        }
-        app_name = "ro"
-        port = 9090
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-    def test_make_pod_spec_without_relation_state(self) -> NoReturn:
-        """Testing make pod spec without relation_state."""
-        image_info = {"upstream-source": "opensourcemano/ro:8"}
-        config = {
-            "enable_ng_ro": True,
-            "database_commonkey": "osm",
-            "log_level": "INFO",
-        }
-        relation_state = {}
-        app_name = "ro"
-        port = 9090
-
-        with self.assertRaises(ValueError):
-            pod_spec.make_pod_spec(image_info, config, relation_state, app_name, port)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/installers/charm/ro/tox.ini b/installers/charm/ro/tox.ini
deleted file mode 100644 (file)
index f3c9144..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright 2021 Canonical Ltd.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact: legal@canonical.com
-#
-# To get in touch with the maintainers, please contact:
-# osm-charmers@lists.launchpad.net
-##
-#######################################################################################
-
-[tox]
-envlist = black, cover, flake8, pylint, yamllint, safety
-skipsdist = true
-
-[tox:jenkins]
-toxworkdir = /tmp/.tox
-
-[testenv]
-basepython = python3.8
-setenv =
-  VIRTUAL_ENV={envdir}
-  PYTHONPATH = {toxinidir}:{toxinidir}/lib:{toxinidir}/src
-  PYTHONDONTWRITEBYTECODE = 1
-deps =  -r{toxinidir}/requirements.txt
-
-
-#######################################################################################
-[testenv:black]
-deps = black
-commands =
-        black --check --diff src/ tests/
-
-
-#######################################################################################
-[testenv:cover]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        coverage
-        nose2
-commands =
-        sh -c 'rm -f nosetests.xml'
-        coverage erase
-        nose2 -C --coverage src
-        coverage report --omit='*tests*'
-        coverage html -d ./cover --omit='*tests*'
-        coverage xml -o coverage.xml --omit=*tests*
-whitelist_externals = sh
-
-
-#######################################################################################
-[testenv:flake8]
-deps =  flake8
-        flake8-import-order
-commands =
-        flake8 src/ tests/
-
-
-#######################################################################################
-[testenv:pylint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        pylint==2.10.2
-commands =
-    pylint -E src/ tests/
-
-
-#######################################################################################
-[testenv:safety]
-setenv =
-        LC_ALL=C.UTF-8
-        LANG=C.UTF-8
-deps =  {[testenv]deps}
-        safety
-commands =
-        - safety check --full-report
-
-
-#######################################################################################
-[testenv:yamllint]
-deps =  {[testenv]deps}
-        -r{toxinidir}/requirements-test.txt
-        yamllint
-commands = yamllint .
-
-#######################################################################################
-[testenv:build]
-passenv=HTTP_PROXY HTTPS_PROXY NO_PROXY
-whitelist_externals =
-  charmcraft
-  sh
-commands =
-  charmcraft pack
-  sh -c 'ubuntu_version=20.04; \
-        architectures="amd64-aarch64-arm64"; \
-        charm_name=`cat metadata.yaml | grep -E "^name: " | cut -f 2 -d " "`; \
-        mv $charm_name"_ubuntu-"$ubuntu_version-$architectures.charm $charm_name.charm'
-
-#######################################################################################
-[flake8]
-ignore =
-        W291,
-        W293,
-        W503,
-        E123,
-        E125,
-        E226,
-        E241,
-exclude =
-        .git,
-        __pycache__,
-        .tox,
-max-line-length = 120
-show-source = True
-builtins = _
-max-complexity = 10
-import-order-style = google
diff --git a/installers/charm/update-bundle-revisions.sh b/installers/charm/update-bundle-revisions.sh
deleted file mode 100755 (executable)
index 1a8d8cb..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-##
-# Copyright 2019 ETSI
-#
-# 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.
-##
-
-charms=`cat bundles/osm/bundle.yaml  | grep cs | grep -v k8s | awk '{print $2}' | tr -d \"`
-for charm_uri in $charms; do
-    charm_without_rev=`echo $charm_uri| rev | cut -d "-" -f 2-5 | rev`
-    latest_revision=`charm show --channel edge $charm_without_rev | grep Revision | awk '{print $2}'`
-    new_charm_uri=$charm_without_rev-$latest_revision
-    old_uri=`echo $charm_uri | sed 's/\//\\\\\//g'`
-    new_uri=`echo $new_charm_uri | sed 's/\//\\\\\//g'`
-    sed -i "s/"$old_uri"/"$new_uri"/g" bundles/osm/bundle.yaml
-done
-
-charms=`cat bundles/osm-ha/bundle.yaml  | grep cs | grep -v k8s | awk '{print $2}' | tr -d \"`
-for charm_uri in $charms; do
-    charm_without_rev=`echo $charm_uri| rev | cut -d "-" -f 2-5 | rev`
-    latest_revision=`charm show --channel edge $charm_without_rev | grep Revision | awk '{print $2}'`
-    new_charm_uri=$charm_without_rev-$latest_revision
-    old_uri=`echo $charm_uri | sed 's/\//\\\\\//g'`
-    new_uri=`echo $new_charm_uri | sed 's/\//\\\\\//g'`
-    sed -i "s/"$old_uri"/"$new_uri"/g" bundles/osm-ha/bundle.yaml
-done
\ No newline at end of file