Integration tests for NG UI charm
[osm/devops.git] / installers / charm / osm-ng-ui / tests / integration / test_charm.py
1 #!/usr/bin/env python3
2 # Copyright 2023 Canonical Ltd.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15 #
16 # For those usages not covered by the Apache License, Version 2.0 please
17 # contact: legal@canonical.com
18 #
19 # To get in touch with the maintainers, please contact:
20 # osm-charmers@lists.launchpad.net
21 #
22 # Learn more about testing at: https://juju.is/docs/sdk/testing
23
24 import asyncio
25 import logging
26 import shlex
27 from pathlib import Path
28
29 import pytest
30 import yaml
31 from pytest_operator.plugin import OpsTest
32
33 logger = logging.getLogger(__name__)
34
35 METADATA = yaml.safe_load(Path("./metadata.yaml").read_text())
36 NG_UI_APP = METADATA["name"]
37
38 # Required charms (needed by NG UI)
39 NBI_CHARM = "osm-nbi"
40 NBI_APP = "nbi"
41 KAFKA_CHARM = "kafka-k8s"
42 KAFKA_APP = "kafka"
43 MONGO_DB_CHARM = "mongodb-k8s"
44 MONGO_DB_APP = "mongodb"
45 PROMETHEUS_CHARM = "osm-prometheus"
46 PROMETHEUS_APP = "prometheus"
47 KEYSTONE_CHARM = "osm-keystone"
48 KEYSTONE_APP = "keystone"
49 MYSQL_CHARM = "charmed-osm-mariadb-k8s"
50 MYSQL_APP = "mysql"
51 ZOOKEEPER_CHARM = "zookeeper-k8s"
52 ZOOKEEPER_APP = "zookeeper"
53
54 INGRESS_CHARM = "nginx-ingress-integrator"
55 INGRESS_APP = "ingress"
56
57 ALL_APPS = [
58 NBI_APP,
59 NG_UI_APP,
60 KAFKA_APP,
61 MONGO_DB_APP,
62 PROMETHEUS_APP,
63 KEYSTONE_APP,
64 MYSQL_APP,
65 ZOOKEEPER_APP,
66 ]
67
68
69 @pytest.mark.abort_on_fail
70 async def test_ng_ui_is_deployed(ops_test: OpsTest):
71 ng_ui_charm = await ops_test.build_charm(".")
72 ng_ui_resources = {"ng-ui-image": METADATA["resources"]["ng-ui-image"]["upstream-source"]}
73 keystone_deploy_cmd = f"juju deploy -m {ops_test.model_full_name} {KEYSTONE_CHARM} {KEYSTONE_APP} --resource keystone-image=opensourcemano/keystone:testing-daily"
74
75 await asyncio.gather(
76 ops_test.model.deploy(
77 ng_ui_charm, resources=ng_ui_resources, application_name=NG_UI_APP, series="focal"
78 ),
79 ops_test.model.deploy(NBI_CHARM, application_name=NBI_APP, channel="beta"),
80 ops_test.model.deploy(KAFKA_CHARM, application_name=KAFKA_APP, channel="stable"),
81 ops_test.model.deploy(
82 MONGO_DB_CHARM, application_name=MONGO_DB_APP, channel="latest/stable"
83 ),
84 ops_test.model.deploy(
85 PROMETHEUS_CHARM, application_name=PROMETHEUS_APP, channel="latest/edge"
86 ),
87 ops_test.model.deploy(ZOOKEEPER_CHARM, application_name=ZOOKEEPER_APP, channel="stable"),
88 ops_test.model.deploy(MYSQL_CHARM, application_name=MYSQL_APP, channel="stable"),
89 # Keystone is deployed separately because the juju python library has a bug where resources
90 # are not properly deployed. See https://github.com/juju/python-libjuju/issues/766
91 ops_test.run(*shlex.split(keystone_deploy_cmd), check=True),
92 )
93
94 async with ops_test.fast_forward():
95 await ops_test.model.wait_for_idle(apps=ALL_APPS, timeout=300)
96 logger.info("Adding relations for other components")
97 await asyncio.gather(
98 ops_test.model.relate(MYSQL_APP, KEYSTONE_APP),
99 ops_test.model.relate(KAFKA_APP, ZOOKEEPER_APP),
100 ops_test.model.relate(KEYSTONE_APP, NBI_APP),
101 ops_test.model.relate(KAFKA_APP, NBI_APP),
102 ops_test.model.relate(MONGO_DB_APP, NBI_APP),
103 ops_test.model.relate(PROMETHEUS_APP, NBI_APP),
104 )
105
106 async with ops_test.fast_forward():
107 await ops_test.model.wait_for_idle(apps=ALL_APPS, timeout=300)
108
109 assert ops_test.model.applications[NG_UI_APP].status == "blocked"
110 unit = ops_test.model.applications[NG_UI_APP].units[0]
111 assert unit.workload_status_message == "need nbi relation"
112
113 logger.info("Adding relations")
114 await ops_test.model.relate(NG_UI_APP, NBI_APP)
115
116 async with ops_test.fast_forward():
117 await ops_test.model.wait_for_idle(apps=ALL_APPS, status="active", timeout=300)
118
119
120 @pytest.mark.abort_on_fail
121 async def test_ng_ui_scales_up(ops_test: OpsTest):
122 logger.info("Scaling up osm-ng-ui")
123 expected_units = 3
124 assert len(ops_test.model.applications[NG_UI_APP].units) == 1
125 await ops_test.model.applications[NG_UI_APP].scale(expected_units)
126 async with ops_test.fast_forward():
127 await ops_test.model.wait_for_idle(
128 apps=[NG_UI_APP], status="active", wait_for_exact_units=expected_units
129 )
130
131
132 @pytest.mark.abort_on_fail
133 async def test_ng_ui_blocks_without_relation(ops_test: OpsTest):
134 await asyncio.gather(ops_test.model.applications[NBI_APP].remove_relation(NBI_APP, NG_UI_APP))
135 async with ops_test.fast_forward():
136 await ops_test.model.wait_for_idle(apps=[NG_UI_APP])
137 assert ops_test.model.applications[NG_UI_APP].status == "blocked"
138 for unit in ops_test.model.applications[NG_UI_APP].units:
139 assert unit.workload_status_message == "need nbi relation"
140 await ops_test.model.relate(NG_UI_APP, NBI_APP)
141 async with ops_test.fast_forward():
142 await ops_test.model.wait_for_idle(apps=ALL_APPS, status="active")
143
144
145 @pytest.mark.abort_on_fail
146 async def test_ng_ui_integration_ingress(ops_test: OpsTest):
147 await asyncio.gather(
148 ops_test.model.deploy(INGRESS_CHARM, application_name=INGRESS_APP, channel="beta"),
149 )
150 async with ops_test.fast_forward():
151 await ops_test.model.wait_for_idle(apps=ALL_APPS + [INGRESS_APP])
152
153 await ops_test.model.relate(NG_UI_APP, INGRESS_APP)
154 async with ops_test.fast_forward():
155 await ops_test.model.wait_for_idle(apps=ALL_APPS + [INGRESS_APP], status="active")