Merge ~mertkirpici/juju-lint:lp/1979686 into juju-lint:master

Proposed by Mert Kirpici
Status: Merged
Approved by: Gabriel Cocenza
Approved revision: 55c3ce784a39196b2e1317c45f15ba1b8b2d58df
Merged at revision: 832f001796ca2e1b15777dfc01d47b6260caa0c2
Proposed branch: ~mertkirpici/juju-lint:lp/1979686
Merge into: juju-lint:master
Diff against target: 1844 lines (+1690/-11)
9 files modified
.gitignore (+1/-1)
CONTRIBUTING.md (+11/-0)
Makefile (+6/-2)
rename.sh (+13/-0)
tests/functional/conftest.py (+129/-0)
tests/functional/requirements.txt (+1/-0)
tests/functional/test_jujulint.py (+49/-0)
tests/resources/fcb-yoga-focal-bundle.yaml (+1442/-0)
tox.ini (+38/-8)
Reviewer Review Type Date Requested Status
Gabriel Cocenza Approve
Eric Chen Needs Information
BootStack Reviewers Pending
Martin Kalcok Pending
Review via email: mp+428809@code.launchpad.net

Commit message

Close LP #1979686

Description of the change

Since the functional tests require the juju-lint application to be
installed to the system, there are two modes of running the tests:
installing the python package to the .tox environment or installing the
snap directly into the system and removing it afterwards. It is worth
mentioning that since `snap install` requires elevated privileges, in
the snap installation case, the pytest fixture install_package() that is
responsible for installing the package will call `sudo install...` and
`sudo remove ...` __requiring passwordless sudo access for the current
user__. The reason for this behaviour rather than enforcing an EUID of
zero is due to the fact that we need access to the user's juju
environment, not root's. Here are examples of both use cases.

Installing the python package:

  $ make functional

Installing the snap:

  $ JUJULINT_TEST_SNAP=./juju-lint_1.0.3_amd64.snap make functional

note the environment variable here. Also note that when the tests are
running against the python package, a WARNING level log will be printed
during the test run to indicate this fact, however when the snap package
is installed, there will be no WARNING printed.

Currently tests are divided into two cases and accompanying markers to
be able to run a subset of them. This might especially come in handy for
skipping the cloud tests during a development cycle since they involve
spinning up a model, deploying an application and destruction of the
model each time the tests are run.

Here is a summary of the two test cases.

- smoke
  - post-build tests as well as tests running against the
    fcb-yoga-focal-bundle.yaml file generated using the
    fcb/sku/stable-yoga-focal branch of the fce-templates repository
- cloud
  - tests that are running against a live model deployed on the local
    cloud via pytest-operator

Combined with the FUNC_ARGS environment variable, these markers could be
used to select tests. Here is an example that runs only the smoke tests:

  $ FUNC_ARGS="-m smoke" make functional

Here is another example utilizing exclusion, since the number of cases
might increase in the future:

  $ FUNC_ARGS="-m 'not cloud'" make functional

To post a comment you must log in.
Revision history for this message
Robert Gildein (rgildein) wrote :

Couple of comments.

Revision history for this message
Mert Kirpici (mertkirpici) wrote :

Addressed Robert's comments and submitting for review.

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Mert Kirpici (mertkirpici) wrote :

Here is the very first run of the functional tests:
https://pastebin.ubuntu.com/p/3JbcT8F9vk/

Revision history for this message
Eric Chen (eric-chen) wrote :

This is a big commit. Could you provide summary of modification? I think we also need to provide this kind of information in launchpad.

e.g.

1. What is the scope of functional tests you focus on? How did you design it?2.
2. Design detail - How to decide the bundle file?

review: Needs Information
Revision history for this message
Mert Kirpici (mertkirpici) wrote :

Resubmitting with these changes:

- Updated the commit message and description
- Introduced pytest marks and FUNC_ARGS variable
- Squashed commits for tidiness

Here is the functest run:
https://pastebin.ubuntu.com/p/QztnK5kmcH/

it includes both snap and python package use cases.

Revision history for this message
Gabriel Cocenza (gabrielcocenza) wrote :

Great job. Thanks for this patch.
Here are some suggestions:

- I think it would be beneficial if some commands are encapsulated into the .tox and/or makefile.

- I see as possible enhancement is to have more than one option as functional tests in the .tox file. E.g: [testenv:func] to build and install the snap locally and run all functional tests, [testenv:func-smoke] to run tests marked as smoke, [testenv:func-dev] run tests using the python package.

- It will be good to have a small session under Developing in the CONTRIBUTING.md with some explanation on how to run the different functional tests (python package, snap, smoke etc).

I also detected a strange behavior [0] when passing the JUJULINT_TEST_SNAP is returning 120 on subprocess check_call, but check_output seems to work normally.

[0] https://pastebin.canonical.com/p/YDYXwwRH4v/

review: Needs Fixing
Revision history for this message
Eric Chen (eric-chen) wrote :

LTGM, just have a question below.

Revision history for this message
Mert Kirpici (mertkirpici) wrote :

Rebased the branch on master after the unit test changes. Resolved conflicts. Addressed the review comments.
Updates include:

- add tox environments func-dev and func-smoke for development purposes
- introduce rename.sh like the charms, `make functional` installs snap and runs the functional tests now
- update CONTRIBUTING.md with functional test info
- fixtures not-requiring cleanup return, do not yield anymore
- move the fcb bundle file under common resources for testing
- fix test_audit_local_cloud. there was an invocation error.

See commit messages for more info.

`make test` output:
https://pastebin.ubuntu.com/p/HVrZzpCnBB/

Revision history for this message
Gabriel Cocenza (gabrielcocenza) wrote :

LGTM. Thanks!

review: Approve
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision 832f001796ca2e1b15777dfc01d47b6260caa0c2

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.gitignore b/.gitignore
2index 6b085ea..764c99f 100644
3--- a/.gitignore
4+++ b/.gitignore
5@@ -13,7 +13,7 @@ __pycache__
6 *.egg-info
7
8 # test artefacts
9-tests/report
10+tests/unit/report
11 .coverage
12
13 # debuild cruft
14diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
15index 1e5c9b9..ef0a32c 100644
16--- a/CONTRIBUTING.md
17+++ b/CONTRIBUTING.md
18@@ -53,6 +53,17 @@ make test # run lint, unittests and functional
19 make build # build the snap
20 make clean # clean the snapcraft lxd containers and the snap files created
21 ```
22+### Functional Tests
23+
24+`make functional` will build the snap, rename it, install it locally and run the tests against the installed snap package. Since this action involves installing a snap package, passwordless `sudo` privileges are needed.
25+However for development purposes, the testing infrastructure also allows for installing `juju-lint` as a python package to a tox environment
26+and running tests against it.
27+In order to invoke:
28+- development smoke suite, which deselects tests running against a live lxd cloud
29+ - `$ tox -e func-smoke`
30+- development full suite, which runs all the functional tests
31+ - `$ tox -e func-dev`
32+
33
34 ## Canonical Contributor Agreement
35
36diff --git a/Makefile b/Makefile
37index 49303b3..4857f3f 100644
38--- a/Makefile
39+++ b/Makefile
40@@ -1,3 +1,7 @@
41+PROJECTPATH=$(dir $(realpath ${MAKEFILE_LIST}))
42+SNAP_NAME=$(shell cat ${PROJECTPATH}/snap/snapcraft.yaml | grep -E '^name:' | awk '{print $$2}')
43+SNAP_FILE=${PROJECTPATH}/${SNAP_NAME}.snap
44+
45 help:
46 @echo "This project supports the following targets"
47 @echo ""
48@@ -13,7 +17,6 @@ help:
49 @echo " make pre-commit - run pre-commit checks on all the files"
50 @echo ""
51
52-
53 lint:
54 @echo "Running lint checks"
55 @tox -e lint
56@@ -32,6 +35,7 @@ reformat:
57 build:
58 @echo "Building the snap"
59 @snapcraft --use-lxd
60+ @bash -c ./rename.sh
61
62 clean:
63 @echo "Cleaning snap"
64@@ -47,7 +51,7 @@ dev-environment:
65
66 functional: build
67 @echo "Executing functional tests using built snap"
68- @tox -e func
69+ @JUJULINT_TEST_SNAP=${SNAP_FILE} tox -e func -- ${FUNC_ARGS}
70
71 pre-commit:
72 @tox -e pre-commit
73diff --git a/rename.sh b/rename.sh
74new file mode 100755
75index 0000000..f7316d0
76--- /dev/null
77+++ b/rename.sh
78@@ -0,0 +1,13 @@
79+#!/bin/bash
80+snap=$(grep -E "^name:" snap/snapcraft.yaml | awk '{print $2}')
81+echo "renaming ${snap}_*.snap to ${snap}.snap"
82+echo -n "pwd: "
83+pwd
84+ls -al
85+echo "Removing previous snap if it exists"
86+if [[ -e "${snap}.snap" ]];
87+then
88+ rm "${snap}.snap"
89+fi
90+echo "Renaming charm here."
91+mv ${snap}_*.snap ${snap}.snap
92diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py
93new file mode 100644
94index 0000000..d26b318
95--- /dev/null
96+++ b/tests/functional/conftest.py
97@@ -0,0 +1,129 @@
98+"""Pytest configuration file for juju-lint tests."""
99+import logging
100+import os
101+import shutil
102+from subprocess import check_call, check_output
103+from textwrap import dedent
104+
105+import pytest
106+
107+
108+def pytest_configure(config):
109+ """Pytest configuration."""
110+ config.addinivalue_line("markers", "smoke: mark test as a smoke test")
111+ config.addinivalue_line("markers", "cloud: mark test as a cloud test")
112+
113+
114+@pytest.fixture(scope="session", autouse=True)
115+def install_package():
116+ """Install the package to the system and cleanup afterwards.
117+
118+ Depending on the environment variable JUJULINT_TEST_SNAP,
119+ it will install the snap or the python package.
120+ """
121+ jujulint_test_snap = os.environ.get("JUJULINT_TEST_SNAP", None)
122+ if jujulint_test_snap:
123+ logging.info(f"Installing {jujulint_test_snap}")
124+ assert os.path.isfile(jujulint_test_snap)
125+ assert (
126+ check_call(
127+ f"sudo snap install --dangerous --classic {jujulint_test_snap}".split()
128+ )
129+ == 0 # noqa
130+ )
131+ assert check_output("which juju-lint".split()).decode().strip() == os.path.join(
132+ "/snap/bin/juju-lint"
133+ )
134+ else:
135+ logging.warning("Installing python package")
136+ assert check_call("python3 -m pip install .".split()) == 0
137+ assert (
138+ check_output("which juju-lint".split())
139+ .decode()
140+ .strip()
141+ .startswith(os.path.join(os.getcwd(), ".tox"))
142+ )
143+
144+ yield jujulint_test_snap
145+
146+ if jujulint_test_snap:
147+ logging.info("Removing snap package juju-lint")
148+ check_call("sudo snap remove juju-lint".split())
149+ else:
150+ logging.info("Uninstalling python package jujulint")
151+ check_call("python3 -m pip uninstall --yes jujulint".split())
152+
153+
154+@pytest.fixture
155+def basedir():
156+ """Return the basedir for the installation.
157+
158+ This will ease testing the rules files that we ship
159+ with the juju-lint snap.
160+ """
161+ if os.environ.get("JUJULINT_TEST_SNAP", None):
162+ basedir = "/snap/juju-lint/current/"
163+ else:
164+ basedir = os.getcwd()
165+ return basedir
166+
167+
168+@pytest.fixture
169+def rules_file(basedir):
170+ """Return the rules file for testing."""
171+ return os.path.join(basedir, "contrib/fcb-yoga-focal.yaml")
172+
173+
174+@pytest.fixture
175+def manual_file():
176+ """Return the bundle file for testing."""
177+ return os.path.join(
178+ os.path.dirname(__file__), "../resources/fcb-yoga-focal-bundle.yaml"
179+ )
180+
181+
182+@pytest.fixture
183+def lint_rules_yaml(basedir, rules_file):
184+ """Return the default lint-rules.yaml file and cleanup."""
185+ lint_rules_yaml_file = os.path.join(os.getcwd(), "lint-rules.yaml")
186+ shutil.copy(rules_file, lint_rules_yaml_file)
187+
188+ includes_dir = os.path.join(os.getcwd(), "includes")
189+ os.symlink(os.path.join(basedir, "contrib/includes"), includes_dir)
190+
191+ yield lint_rules_yaml_file
192+
193+ os.unlink(lint_rules_yaml_file)
194+ os.unlink(includes_dir)
195+
196+
197+@pytest.fixture
198+def local_cloud():
199+ """Prepare the local configuration file for juju-lint.
200+
201+ If there's an existing configuration directory, back it up
202+ first and then recover.
203+ """
204+ local_cloud_name = "test"
205+ backup = False
206+ local_config_dir = os.path.join(os.path.expanduser("~"), ".config/juju-lint")
207+ local_config_file = os.path.join(local_config_dir, "config.yaml")
208+ if os.path.isdir(local_config_dir):
209+ logging.info("Backing up existing config directory")
210+ shutil.move(local_config_dir, local_config_dir + ".bak")
211+ backup = True
212+ os.makedirs(local_config_dir)
213+ with open(local_config_file, "w") as config_yaml:
214+ config_yaml_str = f"""\
215+ clouds:
216+ {local_cloud_name}:
217+ type: openstack
218+ """
219+ config_yaml.write(dedent(config_yaml_str))
220+
221+ yield local_cloud_name
222+
223+ shutil.rmtree(local_config_dir)
224+ if backup:
225+ logging.info("Restoring backup")
226+ shutil.move(local_config_dir + ".bak", local_config_dir)
227diff --git a/tests/functional/requirements.txt b/tests/functional/requirements.txt
228new file mode 100644
229index 0000000..2220b6c
230--- /dev/null
231+++ b/tests/functional/requirements.txt
232@@ -0,0 +1 @@
233+pytest-operator
234\ No newline at end of file
235diff --git a/tests/functional/test_jujulint.py b/tests/functional/test_jujulint.py
236new file mode 100644
237index 0000000..e15e9b6
238--- /dev/null
239+++ b/tests/functional/test_jujulint.py
240@@ -0,0 +1,49 @@
241+"""Functional tests for juju-lint."""
242+import json
243+import socket
244+from subprocess import check_call, check_output
245+
246+import pytest
247+
248+
249+@pytest.mark.smoke
250+def test_juju_lint_startup():
251+ """Test starting juju-lint and print help string."""
252+ assert check_call("juju-lint --help".split()) == 0
253+
254+
255+@pytest.mark.smoke
256+def test_load_rules_file_from_path(rules_file, manual_file):
257+ """Test loading the rules file via command line argument."""
258+ assert check_call(f"juju-lint -c {rules_file} {manual_file}".split()) == 0
259+
260+
261+@pytest.mark.smoke
262+def test_load_default_rules_file(lint_rules_yaml, manual_file):
263+ """Test loading the default rules file."""
264+ assert check_call(f"juju-lint {manual_file}".split()) == 0
265+
266+
267+@pytest.mark.smoke
268+def test_json_output(rules_file, manual_file):
269+ """Test json output."""
270+ assert json.loads(
271+ check_output(
272+ f"juju-lint --format json -c {rules_file} {manual_file}".split()
273+ ).decode()
274+ )
275+
276+
277+@pytest.mark.cloud
278+async def test_audit_local_cloud(ops_test, local_cloud, rules_file):
279+ """Test running juju-lint against a live local cloud."""
280+ await ops_test.model.deploy("ubuntu")
281+ await ops_test.model.wait_for_idle()
282+ returncode, stdout, stderr = await ops_test.run(
283+ *f"juju-lint -c {rules_file}".split()
284+ )
285+ assert (
286+ f"[{local_cloud}] Linting model information for {socket.getfqdn()}, "
287+ f"controller {ops_test.controller_name}, model {ops_test.model_name}" in stderr
288+ )
289+ assert returncode == 0
290diff --git a/tests/resources/fcb-yoga-focal-bundle.yaml b/tests/resources/fcb-yoga-focal-bundle.yaml
291new file mode 100644
292index 0000000..de6364c
293--- /dev/null
294+++ b/tests/resources/fcb-yoga-focal-bundle.yaml
295@@ -0,0 +1,1442 @@
296+applications:
297+ aodh:
298+ bindings:
299+ ? ''
300+ : oam-space
301+ admin: internal-space
302+ amqp: internal-space
303+ certificates: internal-space
304+ identity-service: internal-space
305+ internal: internal-space
306+ public: public-space
307+ shared-db: internal-space
308+ channel: yoga/stable
309+ charm: aodh
310+ num_units: 3
311+ options:
312+ openstack-origin: cloud:focal-yoga
313+ region: RegionOne
314+ use-internal-endpoints: true
315+ to:
316+ - lxd:1
317+ - lxd:4
318+ - lxd:7
319+ aodh-mysql-router:
320+ bindings:
321+ ? ''
322+ : oam-space
323+ db-router: internal-space
324+ shared-db: internal-space
325+ channel: latest/edge
326+ charm: mysql-router
327+ barbican:
328+ bindings:
329+ ? ''
330+ : oam-space
331+ admin: internal-space
332+ amqp: internal-space
333+ certificates: internal-space
334+ identity-service: internal-space
335+ internal: internal-space
336+ public: public-space
337+ secrets: internal-space
338+ shared-db: internal-space
339+ channel: yoga/stable
340+ charm: barbican
341+ num_units: 3
342+ options:
343+ openstack-origin: cloud:focal-yoga
344+ region: RegionOne
345+ use-internal-endpoints: true
346+ to:
347+ - lxd:2
348+ - lxd:5
349+ - lxd:8
350+ barbican-mysql-router:
351+ bindings:
352+ ? ''
353+ : oam-space
354+ db-router: internal-space
355+ shared-db: internal-space
356+ channel: latest/edge
357+ charm: mysql-router
358+ barbican-vault:
359+ bindings:
360+ ? ''
361+ : oam-space
362+ certificates: internal-space
363+ secrets: internal-space
364+ secrets-storage: internal-space
365+ channel: yoga/stable
366+ charm: barbican-vault
367+ bcache-tuning:
368+ bindings:
369+ ? ''
370+ : oam-space
371+ charm: bcache-tuning
372+ canonical-livepatch:
373+ bindings:
374+ ? ''
375+ : oam-space
376+ charm: canonical-livepatch
377+ options:
378+ livepatch_key: FCE_TEMPLATE
379+ ceilometer:
380+ bindings:
381+ ? ''
382+ : oam-space
383+ admin: internal-space
384+ amqp: internal-space
385+ certificates: internal-space
386+ identity-credentials: internal-space
387+ internal: internal-space
388+ public: public-space
389+ shared-db: internal-space
390+ channel: yoga/stable
391+ charm: ceilometer
392+ num_units: 3
393+ options:
394+ openstack-origin: cloud:focal-yoga
395+ region: RegionOne
396+ use-internal-endpoints: true
397+ to:
398+ - lxd:0
399+ - lxd:3
400+ - lxd:6
401+ ceilometer-agent:
402+ bindings:
403+ ? ''
404+ : oam-space
405+ amqp: internal-space
406+ channel: yoga/stable
407+ charm: ceilometer-agent
408+ options:
409+ use-internal-endpoints: true
410+ ceph-dashboard:
411+ bindings:
412+ ? ''
413+ : oam-space
414+ certificates: internal-space
415+ channel: quincy/stable
416+ charm: ceph-dashboard
417+ options:
418+ grafana-api-url: https://grafana.maas:3000
419+ ceph-mon:
420+ bindings:
421+ ? ''
422+ : oam-space
423+ admin: ceph-access-space
424+ client: ceph-access-space
425+ cluster: ceph-replica-space
426+ osd: ceph-access-space
427+ public: ceph-access-space
428+ radosgw: ceph-access-space
429+ channel: quincy/stable
430+ charm: ceph-mon
431+ num_units: 3
432+ options:
433+ customize-failure-domain: true
434+ expected-osd-count: FCE_TEMPLATE
435+ source: cloud:focal-yoga
436+ to:
437+ - lxd:1
438+ - lxd:4
439+ - lxd:7
440+ ceph-osd:
441+ bindings:
442+ ? ''
443+ : oam-space
444+ cluster: ceph-replica-space
445+ mon: ceph-access-space
446+ public: ceph-access-space
447+ secrets-storage: internal-space
448+ channel: quincy/stable
449+ charm: ceph-osd
450+ num_units: 9
451+ options:
452+ aa-profile-mode: complain
453+ autotune: false
454+ bluestore: true
455+ customize-failure-domain: true
456+ osd-devices: /dev/disk/by-dname/FCE_TEMPLATE
457+ osd-encrypt: true
458+ osd-encrypt-keymanager: vault
459+ source: cloud:focal-yoga
460+ to:
461+ - '0'
462+ - '1'
463+ - '2'
464+ - '3'
465+ - '4'
466+ - '5'
467+ - '6'
468+ - '7'
469+ - '8'
470+ ceph-radosgw:
471+ bindings:
472+ ? ''
473+ : oam-space
474+ admin: internal-space
475+ certificates: internal-space
476+ identity-service: internal-space
477+ internal: internal-space
478+ mon: ceph-access-space
479+ public: public-space
480+ channel: quincy/stable
481+ charm: ceph-radosgw
482+ constraints: spaces=ceph-access-space
483+ num_units: 3
484+ options:
485+ region: RegionOne
486+ source: cloud:focal-yoga
487+ to:
488+ - lxd:2
489+ - lxd:5
490+ - lxd:8
491+ cinder:
492+ bindings:
493+ ? ''
494+ : oam-space
495+ admin: internal-space
496+ amqp: internal-space
497+ certificates: internal-space
498+ identity-service: internal-space
499+ internal: internal-space
500+ public: public-space
501+ shared-db: internal-space
502+ channel: yoga/stable
503+ charm: cinder
504+ constraints: spaces=ceph-access-space
505+ num_units: 3
506+ options:
507+ block-device: None
508+ glance-api-version: 2
509+ openstack-origin: cloud:focal-yoga
510+ region: RegionOne
511+ use-internal-endpoints: true
512+ to:
513+ - lxd:0
514+ - lxd:3
515+ - lxd:6
516+ cinder-ceph:
517+ bindings:
518+ ? ''
519+ : oam-space
520+ ceph: ceph-access-space
521+ channel: yoga/stable
522+ charm: cinder-ceph
523+ cinder-mysql-router:
524+ bindings:
525+ ? ''
526+ : oam-space
527+ db-router: internal-space
528+ shared-db: internal-space
529+ channel: latest/edge
530+ charm: mysql-router
531+ designate:
532+ bindings:
533+ ? ''
534+ : oam-space
535+ admin: internal-space
536+ amqp: internal-space
537+ certificates: internal-space
538+ coordinator-memcached: internal-space
539+ dns-backend: internal-space
540+ identity-service: internal-space
541+ internal: internal-space
542+ public: public-space
543+ shared-db: internal-space
544+ channel: yoga/stable
545+ charm: designate
546+ num_units: 3
547+ options:
548+ nameservers: FCE_TEMPLATE
549+ openstack-origin: cloud:focal-yoga
550+ region: RegionOne
551+ use-internal-endpoints: true
552+ to:
553+ - lxd:1
554+ - lxd:4
555+ - lxd:7
556+ designate-bind:
557+ bindings:
558+ ? ''
559+ : oam-space
560+ certificates: internal-space
561+ dns-backend: internal-space
562+ dns-frontend: oam-space
563+ channel: yoga/stable
564+ charm: designate-bind
565+ num_units: 2
566+ options:
567+ allowed_nets: FCE_TEMPLATE
568+ disable-dnssec-validation: true
569+ forwarders: FCE_TEMPLATE
570+ recursion: true
571+ use-internal-endpoints: true
572+ to:
573+ - memcached/0
574+ - memcached/1
575+ designate-mysql-router:
576+ bindings:
577+ ? ''
578+ : oam-space
579+ db-router: internal-space
580+ shared-db: internal-space
581+ channel: latest/edge
582+ charm: mysql-router
583+ easyrsa:
584+ bindings:
585+ ? ''
586+ : oam-space
587+ client: internal-space
588+ charm: easyrsa
589+ num_units: 1
590+ to:
591+ - lxd:6
592+ etcd:
593+ bindings:
594+ ? ''
595+ : oam-space
596+ certificates: internal-space
597+ db: internal-space
598+ charm: etcd
599+ num_units: 3
600+ options:
601+ channel: 3.4/stable
602+ to:
603+ - lxd:2
604+ - lxd:5
605+ - lxd:8
606+ filebeat:
607+ bindings:
608+ ? ''
609+ : oam-space
610+ charm: filebeat
611+ options:
612+ logpath: /var/log/*.log
613+ glance:
614+ bindings:
615+ ? ''
616+ : oam-space
617+ admin: internal-space
618+ amqp: internal-space
619+ ceph: ceph-access-space
620+ certificates: internal-space
621+ identity-service: internal-space
622+ internal: internal-space
623+ public: public-space
624+ shared-db: internal-space
625+ channel: yoga/stable
626+ charm: glance
627+ constraints: spaces=ceph-access-space
628+ num_units: 3
629+ options:
630+ openstack-origin: cloud:focal-yoga
631+ region: RegionOne
632+ use-internal-endpoints: true
633+ to:
634+ - lxd:0
635+ - lxd:3
636+ - lxd:6
637+ glance-mysql-router:
638+ bindings:
639+ ? ''
640+ : oam-space
641+ db-router: internal-space
642+ shared-db: internal-space
643+ channel: latest/edge
644+ charm: mysql-router
645+ glance-simplestreams-sync:
646+ bindings:
647+ ? ''
648+ : oam-space
649+ certificates: internal-space
650+ identity-service: internal-space
651+ channel: yoga/stable
652+ charm: glance-simplestreams-sync
653+ num_units: 1
654+ options:
655+ mirror_list: '[{ url: "http://cloud-images.ubuntu.com/releases/", name_prefix:
656+ "ubuntu:released", path: "streams/v1/index.sjson", max: 1, item_filters: ["release~(bionic|focal)",
657+ "arch~(x86_64|amd64)", "ftype~(disk1.img|disk.img)"] }]'
658+ region: RegionOne
659+ to:
660+ - lxd:7
661+ gnocchi:
662+ bindings:
663+ ? ''
664+ : oam-space
665+ admin: internal-space
666+ amqp: internal-space
667+ certificates: internal-space
668+ coordinator-memcached: internal-space
669+ identity-service: internal-space
670+ internal: internal-space
671+ public: public-space
672+ shared-db: internal-space
673+ storage-ceph: ceph-access-space
674+ channel: yoga/stable
675+ charm: gnocchi
676+ num_units: 3
677+ options:
678+ openstack-origin: cloud:focal-yoga
679+ region: RegionOne
680+ use-internal-endpoints: true
681+ to:
682+ - lxd:1
683+ - lxd:4
684+ - lxd:7
685+ gnocchi-mysql-router:
686+ bindings:
687+ ? ''
688+ : oam-space
689+ db-router: internal-space
690+ shared-db: internal-space
691+ channel: latest/edge
692+ charm: mysql-router
693+ hacluster-aodh:
694+ bindings:
695+ ? ''
696+ : oam-space
697+ channel: 2.0.3/stable
698+ charm: hacluster
699+ options:
700+ cluster_count: 3
701+ hacluster-barbican:
702+ bindings:
703+ ? ''
704+ : oam-space
705+ channel: 2.0.3/stable
706+ charm: hacluster
707+ options:
708+ cluster_count: 3
709+ hacluster-ceilometer:
710+ bindings:
711+ ? ''
712+ : oam-space
713+ channel: 2.0.3/stable
714+ charm: hacluster
715+ options:
716+ cluster_count: 3
717+ hacluster-ceph-radosgw:
718+ bindings:
719+ ? ''
720+ : oam-space
721+ channel: 2.0.3/stable
722+ charm: hacluster
723+ options:
724+ cluster_count: 3
725+ hacluster-cinder:
726+ bindings:
727+ ? ''
728+ : oam-space
729+ channel: 2.0.3/stable
730+ charm: hacluster
731+ options:
732+ cluster_count: 3
733+ hacluster-designate:
734+ bindings:
735+ ? ''
736+ : oam-space
737+ channel: 2.0.3/stable
738+ charm: hacluster
739+ options:
740+ cluster_count: 3
741+ hacluster-glance:
742+ bindings:
743+ ? ''
744+ : oam-space
745+ channel: 2.0.3/stable
746+ charm: hacluster
747+ options:
748+ cluster_count: 3
749+ hacluster-gnocchi:
750+ bindings:
751+ ? ''
752+ : oam-space
753+ channel: 2.0.3/stable
754+ charm: hacluster
755+ options:
756+ cluster_count: 3
757+ hacluster-heat:
758+ bindings:
759+ ? ''
760+ : oam-space
761+ channel: 2.0.3/stable
762+ charm: hacluster
763+ options:
764+ cluster_count: 3
765+ hacluster-keystone:
766+ bindings:
767+ ? ''
768+ : oam-space
769+ channel: 2.0.3/stable
770+ charm: hacluster
771+ options:
772+ cluster_count: 3
773+ hacluster-neutron-api:
774+ bindings:
775+ ? ''
776+ : oam-space
777+ channel: 2.0.3/stable
778+ charm: hacluster
779+ options:
780+ cluster_count: 3
781+ hacluster-nova-cloud-controller:
782+ bindings:
783+ ? ''
784+ : oam-space
785+ channel: 2.0.3/stable
786+ charm: hacluster
787+ options:
788+ cluster_count: 3
789+ hacluster-octavia:
790+ bindings:
791+ ? ''
792+ : oam-space
793+ channel: 2.0.3/stable
794+ charm: hacluster
795+ options:
796+ cluster_count: 3
797+ hacluster-openstack-dashboard:
798+ bindings:
799+ ? ''
800+ : oam-space
801+ channel: 2.0.3/stable
802+ charm: hacluster
803+ options:
804+ cluster_count: 3
805+ hacluster-placement:
806+ bindings:
807+ ? ''
808+ : oam-space
809+ channel: 2.0.3/stable
810+ charm: hacluster
811+ options:
812+ cluster_count: 3
813+ hacluster-vault:
814+ bindings:
815+ ? ''
816+ : oam-space
817+ channel: 2.0.3/stable
818+ charm: hacluster
819+ options:
820+ cluster_count: 3
821+ heat:
822+ bindings:
823+ ? ''
824+ : oam-space
825+ admin: internal-space
826+ amqp: internal-space
827+ certificates: internal-space
828+ identity-service: internal-space
829+ internal: internal-space
830+ public: public-space
831+ shared-db: internal-space
832+ channel: yoga/stable
833+ charm: heat
834+ num_units: 3
835+ options:
836+ openstack-origin: cloud:focal-yoga
837+ region: RegionOne
838+ use-internal-endpoints: true
839+ to:
840+ - lxd:2
841+ - lxd:5
842+ - lxd:8
843+ heat-mysql-router:
844+ bindings:
845+ ? ''
846+ : oam-space
847+ db-router: internal-space
848+ shared-db: internal-space
849+ channel: latest/edge
850+ charm: mysql-router
851+ homer-dashboard:
852+ bindings:
853+ ? ''
854+ : oam-space
855+ application-dashboard: public-space
856+ charm: bootstack-charmers-homer-dashboard
857+ num_units: 1
858+ to:
859+ - lxd:8
860+ keystone:
861+ bindings:
862+ ? ''
863+ : oam-space
864+ admin: internal-space
865+ certificates: internal-space
866+ identity-credentials: internal-space
867+ identity-service: internal-space
868+ internal: internal-space
869+ public: public-space
870+ shared-db: internal-space
871+ channel: yoga/stable
872+ charm: keystone
873+ num_units: 3
874+ options:
875+ openstack-origin: cloud:focal-yoga
876+ preferred-api-version: 3
877+ region: RegionOne
878+ token-expiration: 86400
879+ to:
880+ - lxd:0
881+ - lxd:3
882+ - lxd:6
883+ keystone-ldap:
884+ bindings:
885+ ? ''
886+ : oam-space
887+ certificates: internal-space
888+ channel: yoga/stable
889+ charm: keystone-ldap
890+ options:
891+ domain-name: FCE_TEMPLATE
892+ ldap-config-flags: FCE_TEMPLATE
893+ ldap-password: FCE_TEMPLATE
894+ ldap-server: FCE_TEMPLATE
895+ ldap-suffix: FCE_TEMPLATE
896+ ldap-user: FCE_TEMPLATE
897+ keystone-mysql-router:
898+ bindings:
899+ ? ''
900+ : oam-space
901+ db-router: internal-space
902+ shared-db: internal-space
903+ channel: latest/edge
904+ charm: mysql-router
905+ landscape-client:
906+ bindings:
907+ ? ''
908+ : oam-space
909+ charm: landscape-client
910+ options:
911+ account-name: standalone
912+ disable-unattended-upgrades: true
913+ ping-url: FCE_TEMPLATE
914+ ssl-public-key: FCE_TEMPLATE
915+ url: FCE_TEMPLATE
916+ lldpd:
917+ bindings:
918+ ? ''
919+ : oam-space
920+ charm: lldpd
921+ options:
922+ interfaces-regex: en*
923+ logrotated:
924+ bindings:
925+ ? ''
926+ : oam-space
927+ charm: logrotated
928+ options:
929+ logrotate-retention: 60
930+ memcached:
931+ bindings:
932+ ? ''
933+ : oam-space
934+ cache: internal-space
935+ charm: memcached
936+ num_units: 2
937+ options:
938+ allow-ufw-ip6-softfail: true
939+ to:
940+ - lxd:3
941+ - lxd:6
942+ mysql-innodb-cluster:
943+ bindings:
944+ ? ''
945+ : oam-space
946+ cluster: internal-space
947+ db-router: internal-space
948+ channel: 8.0/stable
949+ charm: mysql-innodb-cluster
950+ num_units: 3
951+ options:
952+ enable-binlogs: true
953+ innodb-buffer-pool-size: 8G
954+ max-connections: 4000
955+ wait-timeout: 3600
956+ to:
957+ - lxd:1
958+ - lxd:4
959+ - lxd:7
960+ neutron-api:
961+ bindings:
962+ ? ''
963+ : oam-space
964+ admin: internal-space
965+ amqp: internal-space
966+ certificates: internal-space
967+ identity-service: internal-space
968+ internal: internal-space
969+ public: public-space
970+ shared-db: internal-space
971+ channel: yoga/stable
972+ charm: neutron-api
973+ num_units: 3
974+ options:
975+ dns-domain: FCE_TEMPLATE
976+ enable-ml2-dns: true
977+ enable-ml2-port-security: true
978+ flat-network-providers: ''
979+ global-physnet-mtu: 9000
980+ manage-neutron-plugin-legacy-mode: false
981+ neutron-security-groups: true
982+ openstack-origin: cloud:focal-yoga
983+ path-mtu: 1558
984+ physical-network-mtus: FCE_TEMPLATE
985+ region: RegionOne
986+ use-internal-endpoints: true
987+ vlan-ranges: FCE_TEMPLATE
988+ to:
989+ - lxd:2
990+ - lxd:5
991+ - lxd:8
992+ neutron-api-mysql-router:
993+ bindings:
994+ ? ''
995+ : oam-space
996+ db-router: internal-space
997+ shared-db: internal-space
998+ channel: latest/edge
999+ charm: mysql-router
1000+ neutron-api-plugin-ovn:
1001+ bindings:
1002+ ? ''
1003+ : oam-space
1004+ certificates: internal-space
1005+ channel: yoga/stable
1006+ charm: neutron-api-plugin-ovn
1007+ nova-cloud-controller:
1008+ bindings:
1009+ ? ''
1010+ : oam-space
1011+ admin: internal-space
1012+ amqp: internal-space
1013+ certificates: internal-space
1014+ cloud-compute: internal-space
1015+ identity-service: internal-space
1016+ internal: internal-space
1017+ memcache: internal-space
1018+ public: public-space
1019+ shared-db: internal-space
1020+ channel: yoga/stable
1021+ charm: nova-cloud-controller
1022+ num_units: 3
1023+ options:
1024+ console-access-protocol: spice
1025+ cpu-allocation-ratio: 16
1026+ network-manager: Neutron
1027+ openstack-origin: cloud:focal-yoga
1028+ ram-allocation-ratio: 1.0
1029+ region: RegionOne
1030+ use-internal-endpoints: true
1031+ to:
1032+ - lxd:0
1033+ - lxd:3
1034+ - lxd:6
1035+ nova-cloud-controller-mysql-router:
1036+ bindings:
1037+ ? ''
1038+ : oam-space
1039+ db-router: internal-space
1040+ shared-db: internal-space
1041+ channel: latest/edge
1042+ charm: mysql-router
1043+ nova-compute:
1044+ bindings:
1045+ ? ''
1046+ : oam-space
1047+ amqp: internal-space
1048+ ceph: ceph-access-space
1049+ cloud-compute: internal-space
1050+ internal: internal-space
1051+ migration: internal-space
1052+ secrets-storage: internal-space
1053+ channel: yoga/stable
1054+ charm: nova-compute
1055+ num_units: 9
1056+ options:
1057+ aa-profile-mode: enforce
1058+ cpu-mode: custom
1059+ cpu-model: FCE_TEMPLATE
1060+ customize-failure-domain: true
1061+ enable-live-migration: true
1062+ enable-resize: true
1063+ encrypt: true
1064+ ephemeral-device: /dev/disk/by-dname/FCE_TEMPLATE
1065+ openstack-origin: cloud:focal-yoga
1066+ reserved-host-memory: 16384
1067+ use-internal-endpoints: true
1068+ to:
1069+ - '0'
1070+ - '1'
1071+ - '2'
1072+ - '3'
1073+ - '4'
1074+ - '5'
1075+ - '6'
1076+ - '7'
1077+ - '8'
1078+ nrpe:
1079+ bindings:
1080+ ? ''
1081+ : oam-space
1082+ charm: nrpe
1083+ ntp:
1084+ bindings:
1085+ ? ''
1086+ : oam-space
1087+ charm: ntp
1088+ options:
1089+ pools: 0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org 2.ubuntu.pool.ntp.org 3.ubuntu.pool.ntp.org
1090+ ntp.ubuntu.com
1091+ source: ''
1092+ verify_ntp_servers: true
1093+ octavia:
1094+ bindings:
1095+ ? ''
1096+ : oam-space
1097+ admin: internal-space
1098+ amqp: internal-space
1099+ certificates: internal-space
1100+ identity-service: internal-space
1101+ internal: internal-space
1102+ public: public-space
1103+ shared-db: internal-space
1104+ channel: yoga/stable
1105+ charm: octavia
1106+ num_units: 3
1107+ options:
1108+ lb-mgmt-controller-cacert: FCE_TEMPLATE
1109+ lb-mgmt-controller-cert: FCE_TEMPLATE
1110+ lb-mgmt-issuing-ca-key-passphrase: FCE_TEMPLATE
1111+ lb-mgmt-issuing-ca-private-key: FCE_TEMPLATE
1112+ lb-mgmt-issuing-cacert: FCE_TEMPLATE
1113+ loadbalancer-topology: ACTIVE_STANDBY
1114+ openstack-origin: cloud:focal-yoga
1115+ region: RegionOne
1116+ use-internal-endpoints: true
1117+ to:
1118+ - lxd:1
1119+ - lxd:4
1120+ - lxd:7
1121+ octavia-dashboard:
1122+ bindings:
1123+ ? ''
1124+ : oam-space
1125+ certificates: internal-space
1126+ dashboard: public-space
1127+ channel: yoga/stable
1128+ charm: octavia-dashboard
1129+ octavia-diskimage-retrofit:
1130+ bindings:
1131+ ? ''
1132+ : oam-space
1133+ certificates: internal-space
1134+ identity-credentials: internal-space
1135+ channel: yoga/stable
1136+ charm: octavia-diskimage-retrofit
1137+ options:
1138+ amp-image-tag: octavia-amphora
1139+ retrofit-uca-pocket: ussuri
1140+ octavia-mysql-router:
1141+ bindings:
1142+ ? ''
1143+ : oam-space
1144+ db-router: internal-space
1145+ shared-db: internal-space
1146+ channel: latest/edge
1147+ charm: mysql-router
1148+ octavia-ovn-chassis:
1149+ bindings:
1150+ ? ''
1151+ : oam-space
1152+ certificates: internal-space
1153+ data: internal-space
1154+ channel: 22.03/stable
1155+ charm: ovn-chassis
1156+ options:
1157+ disable-mlockall: true
1158+ ovn-bridge-mappings: FCE_TEMPLATE
1159+ openstack-dashboard:
1160+ bindings:
1161+ ? ''
1162+ : oam-space
1163+ certificates: internal-space
1164+ dashboard-plugin: public-space
1165+ identity-service: internal-space
1166+ shared-db: internal-space
1167+ channel: yoga/stable
1168+ charm: openstack-dashboard
1169+ num_units: 3
1170+ options:
1171+ endpoint-type: publicURL
1172+ neutron-network-l3ha: true
1173+ neutron-network-lb: true
1174+ openstack-origin: cloud:focal-yoga
1175+ password-retrieve: true
1176+ secret: FCE_TEMPLATE
1177+ webroot: /
1178+ to:
1179+ - lxd:2
1180+ - lxd:5
1181+ - lxd:8
1182+ openstack-dashboard-mysql-router:
1183+ bindings:
1184+ ? ''
1185+ : oam-space
1186+ db-router: internal-space
1187+ shared-db: internal-space
1188+ channel: latest/edge
1189+ charm: mysql-router
1190+ openstack-service-checks:
1191+ bindings:
1192+ ? ''
1193+ : oam-space
1194+ identity-credentials: internal-space
1195+ charm: openstack-service-checks
1196+ num_units: 1
1197+ options:
1198+ s3_check_params: /
1199+ to:
1200+ - lxd:1
1201+ ovn-central:
1202+ bindings:
1203+ ? ''
1204+ : oam-space
1205+ certificates: internal-space
1206+ channel: 22.03/stable
1207+ charm: ovn-central
1208+ num_units: 3
1209+ options:
1210+ source: cloud:focal-yoga
1211+ to:
1212+ - lxd:0
1213+ - lxd:3
1214+ - lxd:6
1215+ ovn-chassis:
1216+ bindings:
1217+ ? ''
1218+ : oam-space
1219+ certificates: internal-space
1220+ data: internal-space
1221+ channel: 22.03/stable
1222+ charm: ovn-chassis
1223+ options:
1224+ bridge-interface-mappings: br-data:FCE_TEMPLATE
1225+ ovn-bridge-mappings: FCE_TEMPLATE
1226+ placement:
1227+ bindings:
1228+ ? ''
1229+ : oam-space
1230+ admin: internal-space
1231+ amqp: internal-space
1232+ certificates: internal-space
1233+ identity-service: internal-space
1234+ internal: internal-space
1235+ public: public-space
1236+ shared-db: internal-space
1237+ channel: yoga/stable
1238+ charm: placement
1239+ num_units: 3
1240+ options:
1241+ openstack-origin: cloud:focal-yoga
1242+ region: RegionOne
1243+ use-internal-endpoints: true
1244+ to:
1245+ - lxd:1
1246+ - lxd:4
1247+ - lxd:7
1248+ placement-mysql-router:
1249+ bindings:
1250+ ? ''
1251+ : oam-space
1252+ db-router: internal-space
1253+ shared-db: internal-space
1254+ channel: latest/edge
1255+ charm: mysql-router
1256+ prometheus-libvirt-exporter:
1257+ bindings:
1258+ ? ''
1259+ : oam-space
1260+ charm: prometheus-libvirt-exporter
1261+ prometheus-openstack-exporter:
1262+ bindings:
1263+ ? ''
1264+ : oam-space
1265+ identity-credentials: internal-space
1266+ prometheus-openstack-exporter-service: oam-space
1267+ charm: prometheus-openstack-exporter
1268+ num_units: 1
1269+ options:
1270+ cpu-allocation-ratio: 16
1271+ ram-allocation-ratio: 1.0
1272+ to:
1273+ - lxd:0
1274+ public-policy-routing:
1275+ bindings:
1276+ ? ''
1277+ : oam-space
1278+ charm: advanced-routing
1279+ options:
1280+ action-managed-update: false
1281+ advanced-routing-config: "[{\n # NOTE: remove comments afterwards, result\
1282+ \ must be a valid JSON\n \"type\": \"table\",\n \"table\": \"public\"\
1283+ \n},{\n \"type\": \"route\",\n \"default_route\": true,\n \"gateway\"\
1284+ : \"FCE_TEMPLATE\", # Replace to gateway address of public network\n \"\
1285+ table\": \"public\",\n \"metric\": \"101\"\n},{\n \"type\": \"rule\"\
1286+ ,\n \"from-net\": \"FCE_TEMPLATE\", # Replace to CIDR of public network\n\
1287+ \ \"table\": \"public\",\n \"priority\": \"101\"\n},{\n \"type\"\
1288+ : \"rule\",\n \"from-net\": \"FCE_TEMPLATE\", # Replace to CIDR of public\
1289+ \ network\n \"to-net\": \"FCE_TEMPLATE\" # Replace to CIDR of public\
1290+ \ network\n}]"
1291+ enable-advanced-routing: true
1292+ rabbitmq-server:
1293+ bindings:
1294+ ? ''
1295+ : oam-space
1296+ amqp: internal-space
1297+ cluster: internal-space
1298+ channel: 3.9/stable
1299+ charm: rabbitmq-server
1300+ num_units: 3
1301+ options:
1302+ cluster-partition-handling: pause_minority
1303+ min-cluster-size: 3
1304+ source: cloud:focal-yoga
1305+ to:
1306+ - lxd:2
1307+ - lxd:5
1308+ - lxd:8
1309+ telegraf:
1310+ bindings:
1311+ ? ''
1312+ : oam-space
1313+ charm: telegraf
1314+ vault:
1315+ bindings:
1316+ ? ''
1317+ : oam-space
1318+ certificates: internal-space
1319+ etcd: internal-space
1320+ secrets: internal-space
1321+ shared-db: internal-space
1322+ channel: 1.7/stable
1323+ charm: vault
1324+ num_units: 3
1325+ to:
1326+ - '10'
1327+ - '11'
1328+ - '9'
1329+ vault-mysql-router:
1330+ bindings:
1331+ ? ''
1332+ : oam-space
1333+ db-router: internal-space
1334+ shared-db: internal-space
1335+ channel: latest/edge
1336+ charm: mysql-router
1337+machines:
1338+ '0':
1339+ constraints: tags=foundation-nodes zones=zone1
1340+ '1':
1341+ constraints: tags=foundation-nodes zones=zone1
1342+ '10':
1343+ constraints: tags=vault zones=zone2
1344+ '11':
1345+ constraints: tags=vault zones=zone3
1346+ '2':
1347+ constraints: tags=foundation-nodes zones=zone1
1348+ '3':
1349+ constraints: tags=foundation-nodes zones=zone2
1350+ '4':
1351+ constraints: tags=foundation-nodes zones=zone2
1352+ '5':
1353+ constraints: tags=foundation-nodes zones=zone2
1354+ '6':
1355+ constraints: tags=foundation-nodes zones=zone3
1356+ '7':
1357+ constraints: tags=foundation-nodes zones=zone3
1358+ '8':
1359+ constraints: tags=foundation-nodes zones=zone3
1360+ '9':
1361+ constraints: tags=vault zones=zone1
1362+saas:
1363+ grafana:
1364+ url: foundations-maas:admin/lma-maas.grafana
1365+ graylog:
1366+ url: foundations-maas:admin/lma-maas.graylog
1367+ landscape-server:
1368+ url: foundations-maas:admin/lma-maas.landscape-server
1369+ nagios:
1370+ url: foundations-maas:admin/lma-maas.nagios
1371+ prometheus:
1372+ url: foundations-maas:admin/lma-maas.prometheus
1373+series: focal
1374+relations:
1375+- ['aodh-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1376+- ['aodh-mysql-router:shared-db', 'aodh:shared-db']
1377+- ['aodh:amqp', 'rabbitmq-server:amqp']
1378+- ['aodh:certificates', 'vault:certificates']
1379+- ['aodh:ha', 'hacluster-aodh:ha']
1380+- ['aodh:identity-service', 'keystone:identity-service']
1381+- ['aodh:juju-info', 'filebeat:beats-host']
1382+- ['aodh:juju-info', 'landscape-client:container']
1383+- ['aodh:juju-info', 'logrotated:juju-info']
1384+- ['aodh:juju-info', 'nrpe:general-info']
1385+- ['aodh:juju-info', 'public-policy-routing:juju-info']
1386+- ['aodh:juju-info', 'telegraf:juju-info']
1387+- ['aodh:nrpe-external-master', 'nrpe:nrpe-external-master']
1388+- ['barbican-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1389+- ['barbican-mysql-router:shared-db', 'barbican:shared-db']
1390+- ['barbican-vault:certificates', 'vault:certificates']
1391+- ['barbican-vault:secrets-storage', 'vault:secrets']
1392+- ['barbican-vault:secrets', 'barbican:secrets']
1393+- ['barbican:amqp', 'rabbitmq-server:amqp']
1394+- ['barbican:certificates', 'vault:certificates']
1395+- ['barbican:ha', 'hacluster-barbican:ha']
1396+- ['barbican:identity-service', 'keystone:identity-service']
1397+- ['barbican:juju-info', 'filebeat:beats-host']
1398+- ['barbican:juju-info', 'landscape-client:container']
1399+- ['barbican:juju-info', 'logrotated:juju-info']
1400+- ['barbican:juju-info', 'nrpe:general-info']
1401+- ['barbican:juju-info', 'public-policy-routing:juju-info']
1402+- ['barbican:juju-info', 'telegraf:juju-info']
1403+- ['bcache-tuning:juju-info', 'ceph-osd:juju-info']
1404+- ['canonical-livepatch:juju-info', 'ceph-osd:juju-info']
1405+- ['canonical-livepatch:juju-info', 'vault:juju-info']
1406+- ['canonical-livepatch:nrpe-external-master', 'nrpe:nrpe-external-master']
1407+- ['ceilometer-agent:amqp', 'rabbitmq-server:amqp']
1408+- ['ceilometer-agent:ceilometer-service', 'ceilometer:ceilometer-service']
1409+- ['ceilometer-agent:nova-ceilometer', 'nova-compute:nova-ceilometer']
1410+- ['ceilometer:amqp', 'rabbitmq-server:amqp']
1411+- ['ceilometer:certificates', 'vault:certificates']
1412+- ['ceilometer:ha', 'hacluster-ceilometer:ha']
1413+- ['ceilometer:identity-credentials', 'keystone:identity-credentials']
1414+- ['ceilometer:identity-notifications', 'keystone:identity-notifications']
1415+- ['ceilometer:juju-info', 'filebeat:beats-host']
1416+- ['ceilometer:juju-info', 'landscape-client:container']
1417+- ['ceilometer:juju-info', 'logrotated:juju-info']
1418+- ['ceilometer:juju-info', 'nrpe:general-info']
1419+- ['ceilometer:juju-info', 'public-policy-routing:juju-info']
1420+- ['ceilometer:juju-info', 'telegraf:juju-info']
1421+- ['ceilometer:metric-service', 'gnocchi:metric-service']
1422+- ['ceilometer:nrpe-external-master', 'nrpe:nrpe-external-master']
1423+- ['ceph-dashboard:certificates', 'vault:certificates']
1424+- ['ceph-dashboard:dashboard', 'ceph-mon:dashboard']
1425+- ['ceph-dashboard:grafana-dashboard', 'grafana:dashboards']
1426+- ['ceph-dashboard:prometheus', 'prometheus:website']
1427+- ['ceph-mon:client', 'cinder-ceph:ceph']
1428+- ['ceph-mon:client', 'glance:ceph']
1429+- ['ceph-mon:client', 'gnocchi:storage-ceph']
1430+- ['ceph-mon:client', 'nova-compute:ceph']
1431+- ['ceph-mon:juju-info', 'filebeat:beats-host']
1432+- ['ceph-mon:juju-info', 'landscape-client:container']
1433+- ['ceph-mon:juju-info', 'logrotated:juju-info']
1434+- ['ceph-mon:juju-info', 'nrpe:general-info']
1435+- ['ceph-mon:juju-info', 'telegraf:juju-info']
1436+- ['ceph-mon:nrpe-external-master', 'nrpe:nrpe-external-master']
1437+- ['ceph-mon:osd', 'ceph-osd:mon']
1438+- ['ceph-mon:prometheus', 'prometheus:target']
1439+- ['ceph-mon:radosgw', 'ceph-radosgw:mon']
1440+- ['ceph-osd:juju-info', 'filebeat:beats-host']
1441+- ['ceph-osd:juju-info', 'landscape-client:container']
1442+- ['ceph-osd:juju-info', 'nrpe:general-info']
1443+- ['ceph-osd:juju-info', 'ntp:juju-info']
1444+- ['ceph-osd:juju-info', 'telegraf:juju-info']
1445+- ['ceph-osd:nrpe-external-master', 'nrpe:nrpe-external-master']
1446+- ['ceph-osd:secrets-storage', 'vault:secrets']
1447+- ['ceph-radosgw:certificates', 'vault:certificates']
1448+- ['ceph-radosgw:ha', 'hacluster-ceph-radosgw:ha']
1449+- ['ceph-radosgw:identity-service', 'keystone:identity-service']
1450+- ['ceph-radosgw:juju-info', 'filebeat:beats-host']
1451+- ['ceph-radosgw:juju-info', 'landscape-client:container']
1452+- ['ceph-radosgw:juju-info', 'logrotated:juju-info']
1453+- ['ceph-radosgw:juju-info', 'nrpe:general-info']
1454+- ['ceph-radosgw:juju-info', 'public-policy-routing:juju-info']
1455+- ['ceph-radosgw:juju-info', 'telegraf:juju-info']
1456+- ['ceph-radosgw:nrpe-external-master', 'nrpe:nrpe-external-master']
1457+- ['cinder-ceph:ceph-access', 'nova-compute:ceph-access']
1458+- ['cinder-ceph:storage-backend', 'cinder:storage-backend']
1459+- ['cinder-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1460+- ['cinder-mysql-router:shared-db', 'cinder:shared-db']
1461+- ['cinder:amqp', 'rabbitmq-server:amqp']
1462+- ['cinder:certificates', 'vault:certificates']
1463+- ['cinder:ha', 'hacluster-cinder:ha']
1464+- ['cinder:identity-service', 'keystone:identity-service']
1465+- ['cinder:image-service', 'glance:image-service']
1466+- ['cinder:juju-info', 'filebeat:beats-host']
1467+- ['cinder:juju-info', 'landscape-client:container']
1468+- ['cinder:juju-info', 'logrotated:juju-info']
1469+- ['cinder:juju-info', 'nrpe:general-info']
1470+- ['cinder:juju-info', 'public-policy-routing:juju-info']
1471+- ['cinder:juju-info', 'telegraf:juju-info']
1472+- ['cinder:nrpe-external-master', 'nrpe:nrpe-external-master']
1473+- ['designate-bind:certificates', 'vault:certificates']
1474+- ['designate-bind:dns-backend', 'designate:dns-backend']
1475+- ['designate-bind:juju-info', 'public-policy-routing:juju-info']
1476+- ['designate-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1477+- ['designate-mysql-router:shared-db', 'designate:shared-db']
1478+- ['designate:amqp', 'rabbitmq-server:amqp']
1479+- ['designate:certificates', 'vault:certificates']
1480+- ['designate:coordinator-memcached', 'memcached:cache']
1481+- ['designate:dnsaas', 'neutron-api:external-dns']
1482+- ['designate:ha', 'hacluster-designate:ha']
1483+- ['designate:identity-service', 'keystone:identity-service']
1484+- ['designate:juju-info', 'filebeat:beats-host']
1485+- ['designate:juju-info', 'landscape-client:container']
1486+- ['designate:juju-info', 'logrotated:juju-info']
1487+- ['designate:juju-info', 'nrpe:general-info']
1488+- ['designate:juju-info', 'public-policy-routing:juju-info']
1489+- ['designate:juju-info', 'telegraf:juju-info']
1490+- ['designate:nrpe-external-master', 'nrpe:nrpe-external-master']
1491+- ['easyrsa:client', 'etcd:certificates']
1492+- ['easyrsa:juju-info', 'filebeat:beats-host']
1493+- ['easyrsa:juju-info', 'landscape-client:container']
1494+- ['easyrsa:juju-info', 'logrotated:juju-info']
1495+- ['easyrsa:juju-info', 'nrpe:general-info']
1496+- ['easyrsa:juju-info', 'telegraf:juju-info']
1497+- ['etcd:db', 'vault:etcd']
1498+- ['etcd:grafana', 'grafana:dashboards']
1499+- ['etcd:juju-info', 'filebeat:beats-host']
1500+- ['etcd:juju-info', 'landscape-client:container']
1501+- ['etcd:juju-info', 'logrotated:juju-info']
1502+- ['etcd:juju-info', 'nrpe:general-info']
1503+- ['etcd:juju-info', 'telegraf:juju-info']
1504+- ['etcd:nrpe-external-master', 'nrpe:nrpe-external-master']
1505+- ['etcd:prometheus', 'prometheus:manual-jobs']
1506+- ['filebeat:beats-host', 'glance-simplestreams-sync:juju-info']
1507+- ['filebeat:beats-host', 'glance:juju-info']
1508+- ['filebeat:beats-host', 'gnocchi:juju-info']
1509+- ['filebeat:beats-host', 'heat:juju-info']
1510+- ['filebeat:beats-host', 'homer-dashboard:juju-info']
1511+- ['filebeat:beats-host', 'keystone:juju-info']
1512+- ['filebeat:beats-host', 'memcached:juju-info']
1513+- ['filebeat:beats-host', 'mysql-innodb-cluster:juju-info']
1514+- ['filebeat:beats-host', 'neutron-api:juju-info']
1515+- ['filebeat:beats-host', 'nova-cloud-controller:juju-info']
1516+- ['filebeat:beats-host', 'octavia:juju-info']
1517+- ['filebeat:beats-host', 'openstack-dashboard:juju-info']
1518+- ['filebeat:beats-host', 'openstack-service-checks:juju-info']
1519+- ['filebeat:beats-host', 'ovn-central:juju-info']
1520+- ['filebeat:beats-host', 'placement:juju-info']
1521+- ['filebeat:beats-host', 'prometheus-openstack-exporter:juju-info']
1522+- ['filebeat:beats-host', 'rabbitmq-server:juju-info']
1523+- ['filebeat:beats-host', 'vault:juju-info']
1524+- ['filebeat:logstash', 'graylog:beats']
1525+- ['glance-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1526+- ['glance-mysql-router:shared-db', 'glance:shared-db']
1527+- ['glance-simplestreams-sync:certificates', 'vault:certificates']
1528+- ['glance-simplestreams-sync:identity-service', 'keystone:identity-service']
1529+- ['glance-simplestreams-sync:juju-info', 'landscape-client:container']
1530+- ['glance-simplestreams-sync:juju-info', 'logrotated:juju-info']
1531+- ['glance-simplestreams-sync:juju-info', 'nrpe:general-info']
1532+- ['glance-simplestreams-sync:juju-info', 'octavia-diskimage-retrofit:juju-info']
1533+- ['glance-simplestreams-sync:juju-info', 'telegraf:juju-info']
1534+- ['glance-simplestreams-sync:nrpe-external-master', 'nrpe:nrpe-external-master']
1535+- ['glance:amqp', 'rabbitmq-server:amqp']
1536+- ['glance:certificates', 'vault:certificates']
1537+- ['glance:ha', 'hacluster-glance:ha']
1538+- ['glance:identity-service', 'keystone:identity-service']
1539+- ['glance:image-service', 'nova-cloud-controller:image-service']
1540+- ['glance:image-service', 'nova-compute:image-service']
1541+- ['glance:juju-info', 'landscape-client:container']
1542+- ['glance:juju-info', 'logrotated:juju-info']
1543+- ['glance:juju-info', 'nrpe:general-info']
1544+- ['glance:juju-info', 'public-policy-routing:juju-info']
1545+- ['glance:juju-info', 'telegraf:juju-info']
1546+- ['glance:nrpe-external-master', 'nrpe:nrpe-external-master']
1547+- ['gnocchi-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1548+- ['gnocchi-mysql-router:shared-db', 'gnocchi:shared-db']
1549+- ['gnocchi:amqp', 'rabbitmq-server:amqp']
1550+- ['gnocchi:certificates', 'vault:certificates']
1551+- ['gnocchi:coordinator-memcached', 'memcached:cache']
1552+- ['gnocchi:ha', 'hacluster-gnocchi:ha']
1553+- ['gnocchi:identity-service', 'keystone:identity-service']
1554+- ['gnocchi:juju-info', 'landscape-client:container']
1555+- ['gnocchi:juju-info', 'logrotated:juju-info']
1556+- ['gnocchi:juju-info', 'nrpe:general-info']
1557+- ['gnocchi:juju-info', 'public-policy-routing:juju-info']
1558+- ['gnocchi:juju-info', 'telegraf:juju-info']
1559+- ['grafana:application-dashboard', 'homer-dashboard:application-dashboard']
1560+- ['grafana:dashboards', 'prometheus-openstack-exporter:dashboards']
1561+- ['graylog:application-dashboard', 'homer-dashboard:application-dashboard']
1562+- ['hacluster-aodh:nrpe-external-master', 'nrpe:nrpe-external-master']
1563+- ['hacluster-barbican:nrpe-external-master', 'nrpe:nrpe-external-master']
1564+- ['hacluster-ceilometer:nrpe-external-master', 'nrpe:nrpe-external-master']
1565+- ['hacluster-ceph-radosgw:nrpe-external-master', 'nrpe:nrpe-external-master']
1566+- ['hacluster-cinder:nrpe-external-master', 'nrpe:nrpe-external-master']
1567+- ['hacluster-designate:nrpe-external-master', 'nrpe:nrpe-external-master']
1568+- ['hacluster-glance:nrpe-external-master', 'nrpe:nrpe-external-master']
1569+- ['hacluster-gnocchi:nrpe-external-master', 'nrpe:nrpe-external-master']
1570+- ['hacluster-heat:ha', 'heat:ha']
1571+- ['hacluster-heat:nrpe-external-master', 'nrpe:nrpe-external-master']
1572+- ['hacluster-keystone:ha', 'keystone:ha']
1573+- ['hacluster-keystone:nrpe-external-master', 'nrpe:nrpe-external-master']
1574+- ['hacluster-neutron-api:ha', 'neutron-api:ha']
1575+- ['hacluster-neutron-api:nrpe-external-master', 'nrpe:nrpe-external-master']
1576+- ['hacluster-nova-cloud-controller:ha', 'nova-cloud-controller:ha']
1577+- ['hacluster-nova-cloud-controller:nrpe-external-master', 'nrpe:nrpe-external-master']
1578+- ['hacluster-octavia:ha', 'octavia:ha']
1579+- ['hacluster-octavia:nrpe-external-master', 'nrpe:nrpe-external-master']
1580+- ['hacluster-openstack-dashboard:ha', 'openstack-dashboard:ha']
1581+- ['hacluster-openstack-dashboard:nrpe-external-master', 'nrpe:nrpe-external-master']
1582+- ['hacluster-placement:ha', 'placement:ha']
1583+- ['hacluster-placement:nrpe-external-master', 'nrpe:nrpe-external-master']
1584+- ['hacluster-vault:ha', 'vault:ha']
1585+- ['hacluster-vault:nrpe-external-master', 'nrpe:nrpe-external-master']
1586+- ['heat-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1587+- ['heat-mysql-router:shared-db', 'heat:shared-db']
1588+- ['heat:amqp', 'rabbitmq-server:amqp']
1589+- ['heat:certificates', 'vault:certificates']
1590+- ['heat:identity-service', 'keystone:identity-service']
1591+- ['heat:juju-info', 'landscape-client:container']
1592+- ['heat:juju-info', 'logrotated:juju-info']
1593+- ['heat:juju-info', 'nrpe:general-info']
1594+- ['heat:juju-info', 'public-policy-routing:juju-info']
1595+- ['heat:juju-info', 'telegraf:juju-info']
1596+- ['heat:nrpe-external-master', 'nrpe:nrpe-external-master']
1597+- ['homer-dashboard:application-dashboard', 'landscape-server:application-dashboard']
1598+- ['homer-dashboard:application-dashboard', 'nagios:application-dashboard']
1599+- ['homer-dashboard:juju-info', 'landscape-client:container']
1600+- ['homer-dashboard:juju-info', 'logrotated:juju-info']
1601+- ['homer-dashboard:juju-info', 'nrpe:general-info']
1602+- ['homer-dashboard:juju-info', 'telegraf:juju-info']
1603+- ['keystone-ldap:certificates', 'vault:certificates']
1604+- ['keystone-ldap:domain-backend', 'keystone:domain-backend']
1605+- ['keystone-mysql-router:db-router', 'mysql-innodb-cluster:db-router']
1606+- ['keystone-mysql-router:shared-db', 'keystone:shared-db']
1607+- ['keystone:certificates', 'vault:certificates']
1608+- ['keystone:identity-credentials', 'octavia-diskimage-retrofit:identity-credentials']
1609+- ['keystone:identity-credentials', 'openstack-service-checks:identity-credentials']
1610+- ['keystone:identity-credentials', 'prometheus-openstack-exporter:identity-credentials']
1611+- ['keystone:identity-notifications', 'openstack-service-checks:identity-notifications']
1612+- ['keystone:identity-service', 'neutron-api:identity-service']
1613+- ['keystone:identity-service', 'nova-cloud-controller:identity-service']
1614+- ['keystone:identity-service', 'octavia:identity-service']
1615+- ['keystone:identity-service', 'openstack-dashboard:identity-service']
1616+- ['keystone:identity-service', 'placement:identity-service']
1617+- ['keystone:juju-info', 'landscape-client:container']
1618+- ['keystone:juju-info', 'logrotated:juju-info']
1619+- ['keystone:juju-info', 'nrpe:general-info']
1620+- ['keystone:juju-info', 'public-policy-routing:juju-info']
1621+- ['keystone:juju-info', 'telegraf:juju-info']
1622+- ['keystone:nrpe-external-master', 'nrpe:nrpe-external-master']
1623+- ['landscape-client:container', 'memcached:juju-info']
1624+- ['landscape-client:container', 'mysql-innodb-cluster:juju-info']
1625+- ['landscape-client:container', 'neutron-api:juju-info']
1626+- ['landscape-client:container', 'nova-cloud-controller:juju-info']
1627+- ['landscape-client:container', 'octavia:juju-info']
1628+- ['landscape-client:container', 'openstack-dashboard:juju-info']
1629+- ['landscape-client:container', 'openstack-service-checks:juju-info']
1630+- ['landscape-client:container', 'ovn-central:juju-info']
1631+- ['landscape-client:container', 'placement:juju-info']
1632+- ['landscape-client:container', 'prometheus-openstack-exporter:juju-info']
1633+- ['landscape-client:container', 'rabbitmq-server:juju-info']
1634+- ['landscape-client:container', 'vault:juju-info']
1635+- ['lldpd:juju-info', 'nova-compute:juju-info']
1636+- ['logrotated:juju-info', 'memcached:juju-info']
1637+- ['logrotated:juju-info', 'mysql-innodb-cluster:juju-info']
1638+- ['logrotated:juju-info', 'neutron-api:juju-info']
1639+- ['logrotated:juju-info', 'nova-cloud-controller:juju-info']
1640+- ['logrotated:juju-info', 'octavia:juju-info']
1641+- ['logrotated:juju-info', 'openstack-dashboard:juju-info']
1642+- ['logrotated:juju-info', 'openstack-service-checks:juju-info']
1643+- ['logrotated:juju-info', 'ovn-central:juju-info']
1644+- ['logrotated:juju-info', 'placement:juju-info']
1645+- ['logrotated:juju-info', 'prometheus-openstack-exporter:juju-info']
1646+- ['logrotated:juju-info', 'rabbitmq-server:juju-info']
1647+- ['logrotated:juju-info', 'vault:juju-info']
1648+- ['memcached:cache', 'nova-cloud-controller:memcache']
1649+- ['memcached:juju-info', 'nrpe:general-info']
1650+- ['memcached:juju-info', 'telegraf:juju-info']
1651+- ['memcached:nrpe-external-master', 'nrpe:nrpe-external-master']
1652+- ['mysql-innodb-cluster:db-router', 'neutron-api-mysql-router:db-router']
1653+- ['mysql-innodb-cluster:db-router', 'nova-cloud-controller-mysql-router:db-router']
1654+- ['mysql-innodb-cluster:db-router', 'octavia-mysql-router:db-router']
1655+- ['mysql-innodb-cluster:db-router', 'openstack-dashboard-mysql-router:db-router']
1656+- ['mysql-innodb-cluster:db-router', 'placement-mysql-router:db-router']
1657+- ['mysql-innodb-cluster:db-router', 'vault-mysql-router:db-router']
1658+- ['mysql-innodb-cluster:juju-info', 'nrpe:general-info']
1659+- ['mysql-innodb-cluster:juju-info', 'telegraf:juju-info']
1660+- ['nagios:monitors', 'nrpe:monitors']
1661+- ['neutron-api-mysql-router:shared-db', 'neutron-api:shared-db']
1662+- ['neutron-api-plugin-ovn:certificates', 'vault:certificates']
1663+- ['neutron-api-plugin-ovn:neutron-plugin', 'neutron-api:neutron-plugin-api-subordinate']
1664+- ['neutron-api-plugin-ovn:ovsdb-cms', 'ovn-central:ovsdb-cms']
1665+- ['neutron-api:amqp', 'rabbitmq-server:amqp']
1666+- ['neutron-api:certificates', 'vault:certificates']
1667+- ['neutron-api:juju-info', 'nrpe:general-info']
1668+- ['neutron-api:juju-info', 'public-policy-routing:juju-info']
1669+- ['neutron-api:juju-info', 'telegraf:juju-info']
1670+- ['neutron-api:neutron-api', 'nova-cloud-controller:neutron-api']
1671+- ['neutron-api:neutron-load-balancer', 'octavia:neutron-api']
1672+- ['neutron-api:nrpe-external-master', 'nrpe:nrpe-external-master']
1673+- ['nova-cloud-controller-mysql-router:shared-db', 'nova-cloud-controller:shared-db']
1674+- ['nova-cloud-controller:amqp', 'rabbitmq-server:amqp']
1675+- ['nova-cloud-controller:certificates', 'vault:certificates']
1676+- ['nova-cloud-controller:cloud-compute', 'nova-compute:cloud-compute']
1677+- ['nova-cloud-controller:juju-info', 'nrpe:general-info']
1678+- ['nova-cloud-controller:juju-info', 'public-policy-routing:juju-info']
1679+- ['nova-cloud-controller:juju-info', 'telegraf:juju-info']
1680+- ['nova-cloud-controller:nrpe-external-master', 'nrpe:nrpe-external-master']
1681+- ['nova-cloud-controller:placement', 'placement:placement']
1682+- ['nova-compute:amqp', 'rabbitmq-server:amqp']
1683+- ['nova-compute:juju-info', 'prometheus-libvirt-exporter:juju-info']
1684+- ['nova-compute:neutron-plugin', 'ovn-chassis:nova-compute']
1685+- ['nova-compute:nrpe-external-master', 'nrpe:nrpe-external-master']
1686+- ['nova-compute:secrets-storage', 'vault:secrets']
1687+- ['nrpe:general-info', 'octavia:juju-info']
1688+- ['nrpe:general-info', 'openstack-dashboard:juju-info']
1689+- ['nrpe:general-info', 'openstack-service-checks:juju-info']
1690+- ['nrpe:general-info', 'ovn-central:juju-info']
1691+- ['nrpe:general-info', 'placement:juju-info']
1692+- ['nrpe:general-info', 'prometheus-openstack-exporter:juju-info']
1693+- ['nrpe:general-info', 'rabbitmq-server:juju-info']
1694+- ['nrpe:general-info', 'vault:juju-info']
1695+- ['nrpe:nrpe-external-master', 'ntp:nrpe-external-master']
1696+- ['nrpe:nrpe-external-master', 'octavia:nrpe-external-master']
1697+- ['nrpe:nrpe-external-master', 'openstack-dashboard:nrpe-external-master']
1698+- ['nrpe:nrpe-external-master', 'openstack-service-checks:nrpe-external-master']
1699+- ['nrpe:nrpe-external-master', 'ovn-central:nrpe-external-master']
1700+- ['nrpe:nrpe-external-master', 'prometheus-libvirt-exporter:nrpe-external-master']
1701+- ['nrpe:nrpe-external-master', 'prometheus-openstack-exporter:nrpe-external-master']
1702+- ['nrpe:nrpe-external-master', 'rabbitmq-server:nrpe-external-master']
1703+- ['nrpe:nrpe-external-master', 'vault:nrpe-external-master']
1704+- ['ntp:juju-info', 'vault:juju-info']
1705+- ['octavia-dashboard:certificates', 'vault:certificates']
1706+- ['octavia-dashboard:dashboard', 'openstack-dashboard:dashboard-plugin']
1707+- ['octavia-diskimage-retrofit:certificates', 'vault:certificates']
1708+- ['octavia-mysql-router:shared-db', 'octavia:shared-db']
1709+- ['octavia-ovn-chassis:certificates', 'vault:certificates']
1710+- ['octavia-ovn-chassis:ovsdb-subordinate', 'octavia:ovsdb-subordinate']
1711+- ['octavia-ovn-chassis:ovsdb', 'ovn-central:ovsdb']
1712+- ['octavia:amqp', 'rabbitmq-server:amqp']
1713+- ['octavia:certificates', 'vault:certificates']
1714+- ['octavia:juju-info', 'public-policy-routing:juju-info']
1715+- ['octavia:juju-info', 'telegraf:juju-info']
1716+- ['octavia:ovsdb-cms', 'ovn-central:ovsdb-cms']
1717+- ['openstack-dashboard-mysql-router:shared-db', 'openstack-dashboard:shared-db']
1718+- ['openstack-dashboard:certificates', 'vault:certificates']
1719+- ['openstack-dashboard:juju-info', 'public-policy-routing:juju-info']
1720+- ['openstack-dashboard:juju-info', 'telegraf:juju-info']
1721+- ['openstack-service-checks:juju-info', 'telegraf:juju-info']
1722+- ['ovn-central:certificates', 'vault:certificates']
1723+- ['ovn-central:juju-info', 'telegraf:juju-info']
1724+- ['ovn-central:ovsdb', 'ovn-chassis:ovsdb']
1725+- ['ovn-chassis:certificates', 'vault:certificates']
1726+- ['placement-mysql-router:shared-db', 'placement:shared-db']
1727+- ['placement:amqp', 'rabbitmq-server:amqp']
1728+- ['placement:certificates', 'vault:certificates']
1729+- ['placement:juju-info', 'public-policy-routing:juju-info']
1730+- ['placement:juju-info', 'telegraf:juju-info']
1731+- ['prometheus-libvirt-exporter:scrape', 'prometheus:target']
1732+- ['prometheus-openstack-exporter:juju-info', 'telegraf:juju-info']
1733+- ['prometheus-openstack-exporter:prometheus-openstack-exporter-service', 'prometheus:target']
1734+- ['prometheus:target', 'telegraf:prometheus-client']
1735+- ['rabbitmq-server:juju-info', 'telegraf:juju-info']
1736+- ['telegraf:juju-info', 'vault:juju-info']
1737+- ['vault-mysql-router:shared-db', 'vault:shared-db']
1738diff --git a/tests/conftest.py b/tests/unit/conftest.py
1739similarity index 100%
1740rename from tests/conftest.py
1741rename to tests/unit/conftest.py
1742diff --git a/tests/requirements.txt b/tests/unit/requirements.txt
1743similarity index 100%
1744rename from tests/requirements.txt
1745rename to tests/unit/requirements.txt
1746diff --git a/tests/test_check_spaces.py b/tests/unit/test_check_spaces.py
1747similarity index 100%
1748rename from tests/test_check_spaces.py
1749rename to tests/unit/test_check_spaces.py
1750diff --git a/tests/test_cli.py b/tests/unit/test_cli.py
1751similarity index 100%
1752rename from tests/test_cli.py
1753rename to tests/unit/test_cli.py
1754diff --git a/tests/test_cloud.py b/tests/unit/test_cloud.py
1755similarity index 100%
1756rename from tests/test_cloud.py
1757rename to tests/unit/test_cloud.py
1758diff --git a/tests/test_jujulint.py b/tests/unit/test_jujulint.py
1759similarity index 100%
1760rename from tests/test_jujulint.py
1761rename to tests/unit/test_jujulint.py
1762diff --git a/tests/test_k8s.py b/tests/unit/test_k8s.py
1763similarity index 100%
1764rename from tests/test_k8s.py
1765rename to tests/unit/test_k8s.py
1766diff --git a/tests/test_logging.py b/tests/unit/test_logging.py
1767similarity index 100%
1768rename from tests/test_logging.py
1769rename to tests/unit/test_logging.py
1770diff --git a/tests/test_openstack.py b/tests/unit/test_openstack.py
1771similarity index 100%
1772rename from tests/test_openstack.py
1773rename to tests/unit/test_openstack.py
1774diff --git a/tox.ini b/tox.ini
1775index e37275c..31ae64d 100644
1776--- a/tox.ini
1777+++ b/tox.ini
1778@@ -18,7 +18,7 @@ skip_missing_interpreters = True
1779 [testenv]
1780 basepython = python3.8
1781 deps =
1782- -r{toxinidir}/tests/requirements.txt
1783+ -r{toxinidir}/tests/unit/requirements.txt
1784 -r{toxinidir}/requirements.txt
1785
1786 [testenv:unit]
1787@@ -30,11 +30,43 @@ commands =
1788 --last-failed-no-failures all \
1789 --cov-fail-under=100 \
1790 --cov-report=term-missing \
1791- --cov-report=annotate:tests/report/coverage-annotated \
1792- --cov-report=html:tests/report/coverage-html \
1793- --html=tests/report/index.html \
1794- --junitxml=tests/report/junit.xml
1795-setenv = PYTHONPATH={toxinidir}/lib
1796+ --cov-report=annotate:tests/unit/report/coverage-annotated \
1797+ --cov-report=html:tests/unit/report/coverage-html \
1798+ --html=tests/unit/report/index.html \
1799+ --junitxml=tests/unit/report/junit.xml \
1800+ --ignore={toxinidir}/tests/functional
1801+setenv = PYTHONPATH={toxinidir}
1802+
1803+[testenv:func]
1804+passenv =
1805+ JUJULINT_TEST_*
1806+deps =
1807+ {[testenv]deps}
1808+ -r{toxinidir}/tests/functional/requirements.txt
1809+commands =
1810+ pytest -v \
1811+ --log-cli-level=WARNING \
1812+ --ignore={toxinidir}/tests/unit \
1813+ {posargs}
1814+
1815+[testenv:func-smoke]
1816+deps =
1817+ {[testenv]deps}
1818+ -r{toxinidir}/tests/functional/requirements.txt
1819+commands =
1820+ pytest -v \
1821+ --log-cli-level=WARNING \
1822+ --ignore={toxinidir}/tests/unit \
1823+ -m smoke
1824+
1825+[testenv:func-dev]
1826+deps =
1827+ {[testenv]deps}
1828+ -r{toxinidir}/tests/functional/requirements.txt
1829+commands =
1830+ pytest -v \
1831+ --log-cli-level=WARNING \
1832+ --ignore={toxinidir}/tests/unit
1833
1834 [testenv:lint]
1835 commands =
1836@@ -48,8 +80,6 @@ commands =
1837 black .
1838 isort .
1839
1840-[testenv:func]
1841-#TODO(gabrielcocenza) add func tests
1842
1843 [pytest]
1844 filterwarnings =

Subscribers

People subscribed via source and target branches