Build jammy charms for osm
[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_image = "opensourcemano/keystone:testing-daily"
74 keystone_deploy_cmd = f"juju deploy -m {ops_test.model_full_name} {KEYSTONE_CHARM} {KEYSTONE_APP} --resource keystone-image={keystone_image} --channel=latest/beta --series jammy"
75
76 await asyncio.gather(
77 ops_test.model.deploy(
78 ng_ui_charm, resources=ng_ui_resources, application_name=NG_UI_APP, series="jammy"
79 ),
80 ops_test.model.deploy(
81 NBI_CHARM, application_name=NBI_APP, channel="latest/beta", series="jammy"
82 ),
83 ops_test.model.deploy(KAFKA_CHARM, application_name=KAFKA_APP, channel="stable"),
84 ops_test.model.deploy(MONGO_DB_CHARM, application_name=MONGO_DB_APP, channel="5/edge"),
85 ops_test.model.deploy(PROMETHEUS_CHARM, application_name=PROMETHEUS_APP, channel="stable"),
86 ops_test.model.deploy(ZOOKEEPER_CHARM, application_name=ZOOKEEPER_APP, channel="stable"),
87 ops_test.model.deploy(MYSQL_CHARM, application_name=MYSQL_APP, channel="stable"),
88 # Keystone is deployed separately because the juju python library has a bug where resources
89 # are not properly deployed. See https://github.com/juju/python-libjuju/issues/766
90 ops_test.run(*shlex.split(keystone_deploy_cmd), check=True),
91 )
92
93 async with ops_test.fast_forward():
94 await ops_test.model.wait_for_idle(apps=ALL_APPS, timeout=300)
95 logger.info("Adding relations for other components")
96 await asyncio.gather(
97 ops_test.model.relate(MYSQL_APP, KEYSTONE_APP),
98 ops_test.model.relate(KAFKA_APP, ZOOKEEPER_APP),
99 ops_test.model.relate(KEYSTONE_APP, NBI_APP),
100 ops_test.model.relate(KAFKA_APP, NBI_APP),
101 ops_test.model.relate("{}:mongodb".format(NBI_APP), "{}:database".format(MONGO_DB_APP)),
102 ops_test.model.relate(PROMETHEUS_APP, NBI_APP),
103 )
104
105 async with ops_test.fast_forward():
106 await ops_test.model.wait_for_idle(apps=ALL_APPS, timeout=300)
107
108 assert ops_test.model.applications[NG_UI_APP].status == "blocked"
109 unit = ops_test.model.applications[NG_UI_APP].units[0]
110 assert unit.workload_status_message == "need nbi relation"
111
112 logger.info("Adding relations for NG-UI")
113 await ops_test.model.relate(NG_UI_APP, NBI_APP)
114
115 async with ops_test.fast_forward():
116 await ops_test.model.wait_for_idle(apps=ALL_APPS, status="active", timeout=300)
117
118
119 @pytest.mark.abort_on_fail
120 async def test_ng_ui_scales_up(ops_test: OpsTest):
121 logger.info("Scaling up osm-ng-ui")
122 expected_units = 3
123 assert len(ops_test.model.applications[NG_UI_APP].units) == 1
124 await ops_test.model.applications[NG_UI_APP].scale(expected_units)
125 async with ops_test.fast_forward():
126 await ops_test.model.wait_for_idle(
127 apps=[NG_UI_APP], status="active", wait_for_exact_units=expected_units
128 )
129
130
131 @pytest.mark.abort_on_fail
132 async def test_ng_ui_blocks_without_relation(ops_test: OpsTest):
133 await asyncio.gather(ops_test.model.applications[NBI_APP].remove_relation(NBI_APP, NG_UI_APP))
134 async with ops_test.fast_forward():
135 await ops_test.model.wait_for_idle(apps=[NG_UI_APP])
136 assert ops_test.model.applications[NG_UI_APP].status == "blocked"
137 for unit in ops_test.model.applications[NG_UI_APP].units:
138 assert unit.workload_status_message == "need nbi relation"
139 await ops_test.model.relate(NG_UI_APP, NBI_APP)
140 async with ops_test.fast_forward():
141 await ops_test.model.wait_for_idle(apps=ALL_APPS, status="active")
142
143
144 @pytest.mark.abort_on_fail
145 async def test_ng_ui_integration_ingress(ops_test: OpsTest):
146 # Temporal workaround due to python-libjuju 2.9.42.2 bug fixed in
147 # https://github.com/juju/python-libjuju/pull/854
148 # To be replaced when juju version 2.9.43 is used.
149 cmd = f"juju deploy {INGRESS_CHARM} {INGRESS_APP} --channel stable"
150 await ops_test.run(*shlex.split(cmd), check=True)
151
152 async with ops_test.fast_forward():
153 await ops_test.model.wait_for_idle(apps=ALL_APPS + [INGRESS_APP])
154
155 await ops_test.model.relate(NG_UI_APP, INGRESS_APP)
156 async with ops_test.fast_forward():
157 await ops_test.model.wait_for_idle(apps=ALL_APPS + [INGRESS_APP], status="active")