From 9c012576afd933a98165adb5374770e84dc685b8 Mon Sep 17 00:00:00 2001 From: David Garcia Date: Mon, 30 Nov 2020 16:58:23 +0100 Subject: [PATCH] Update squid charm --- magma/squid_cnf/charms/squid/actions/addurl | 13 - magma/squid_cnf/charms/squid/config.yaml | 6 +- magma/squid_cnf/charms/squid/dispatch | 3 + magma/squid_cnf/charms/squid/hooks/install | 2 +- magma/squid_cnf/charms/squid/hooks/start | 1 + .../charms/squid/hooks/upgrade-charm | 1 + magma/squid_cnf/charms/squid/lib/.empty | 0 .../charms/squid/lib/ops/__init__.py | 18 - magma/squid_cnf/charms/squid/lib/ops/charm.py | 562 ----- magma/squid_cnf/charms/squid/lib/ops/main.py | 235 --- magma/squid_cnf/charms/squid/metadata.yaml | 9 +- magma/squid_cnf/charms/squid/mod/.empty | 0 .../charms/squid/mod/operator/.flake8 | 2 - .../charms/squid/mod/operator/.gitignore | 4 - .../squid/mod/operator/.readthedocs.yaml | 7 - .../charms/squid/mod/operator/.travis.yml | 24 - .../charms/squid/mod/operator/README.md | 137 -- .../charms/squid/mod/operator/build_docs | 18 - .../charms/squid/mod/operator/docs/conf.py | 89 - .../charms/squid/mod/operator/docs/index.rst | 58 - .../squid/mod/operator/docs/requirements.txt | 1 - .../charms/squid/mod/operator/ops/charm.py | 562 ----- .../squid/mod/operator/ops/framework.py | 1134 ---------- .../squid/mod/operator/ops/jujuversion.py | 85 - .../charms/squid/mod/operator/ops/log.py | 47 - .../charms/squid/mod/operator/ops/main.py | 235 --- .../charms/squid/mod/operator/ops/model.py | 915 -------- .../charms/squid/mod/operator/ops/testing.py | 477 ----- .../squid/mod/operator/requirements.txt | 1 - .../charms/squid/mod/operator/run_tests | 3 - .../charms/squid/mod/operator/setup.py | 39 - .../squid/mod/operator/test/__init__.py | 0 .../squid/mod/operator/test/bin/relation-ids | 11 - .../squid/mod/operator/test/bin/relation-list | 16 - .../test/charms/test_main/config.yaml | 1 - .../test/charms/test_main/lib/__init__.py | 0 .../operator/test/charms/test_main/lib/ops | 1 - .../test/charms/test_main/metadata.yaml | 26 - .../test/charms/test_main/src/charm.py | 208 -- .../squid/mod/operator/test/test_charm.py | 323 --- .../squid/mod/operator/test/test_framework.py | 1727 --------------- .../squid/mod/operator/test/test_helpers.py | 81 - .../squid/mod/operator/test/test_infra.py | 130 -- .../mod/operator/test/test_jujuversion.py | 130 -- .../squid/mod/operator/test/test_log.py | 140 -- .../squid/mod/operator/test/test_main.py | 675 ------ .../squid/mod/operator/test/test_model.py | 1288 ------------ .../squid/mod/operator/test/test_testing.py | 756 ------- magma/squid_cnf/charms/squid/requirements.txt | 3 + magma/squid_cnf/charms/squid/squid.charm | Bin 0 -> 601730 bytes magma/squid_cnf/charms/squid/src/charm.py | 178 +- .../charms/squid/template/squid.conf | 26 + .../venv/Jinja2-2.11.2.dist-info/INSTALLER | 1 + .../venv/Jinja2-2.11.2.dist-info/LICENSE.rst | 28 + .../venv/Jinja2-2.11.2.dist-info/METADATA | 106 + .../squid/venv/Jinja2-2.11.2.dist-info/RECORD | 61 + .../squid/venv/Jinja2-2.11.2.dist-info/WHEEL | 6 + .../Jinja2-2.11.2.dist-info/entry_points.txt | 3 + .../Jinja2-2.11.2.dist-info/top_level.txt | 1 + .../venv/MarkupSafe-1.1.1.dist-info/INSTALLER | 1 + .../MarkupSafe-1.1.1.dist-info/LICENSE.txt | 28 + .../venv/MarkupSafe-1.1.1.dist-info/METADATA | 105 + .../venv/MarkupSafe-1.1.1.dist-info/RECORD | 16 + .../venv/MarkupSafe-1.1.1.dist-info/WHEEL | 5 + .../MarkupSafe-1.1.1.dist-info/top_level.txt | 1 + .../venv/PyYAML-5.3.1.dist-info/INSTALLER | 1 + .../squid/venv/PyYAML-5.3.1.dist-info/LICENSE | 20 + .../venv/PyYAML-5.3.1.dist-info/METADATA | 41 + .../squid/venv/PyYAML-5.3.1.dist-info/RECORD | 40 + .../squid/venv/PyYAML-5.3.1.dist-info/WHEEL | 5 + .../venv/PyYAML-5.3.1.dist-info/top_level.txt | 2 + .../charms/squid/venv/jinja2/__init__.py | 44 + .../charms/squid/venv/jinja2/_compat.py | 132 ++ .../charms/squid/venv/jinja2/_identifier.py | 6 + .../charms/squid/venv/jinja2/asyncfilters.py | 158 ++ .../charms/squid/venv/jinja2/asyncsupport.py | 264 +++ .../charms/squid/venv/jinja2/bccache.py | 350 ++++ .../charms/squid/venv/jinja2/compiler.py | 1843 +++++++++++++++++ .../charms/squid/venv/jinja2/constants.py | 21 + .../charms/squid/venv/jinja2/debug.py | 268 +++ .../charms/squid/venv/jinja2/defaults.py | 44 + .../charms/squid/venv/jinja2/environment.py | 1362 ++++++++++++ .../charms/squid/venv/jinja2/exceptions.py | 177 ++ .../squid_cnf/charms/squid/venv/jinja2/ext.py | 704 +++++++ .../charms/squid/venv/jinja2/filters.py | 1382 ++++++++++++ .../charms/squid/venv/jinja2/idtracking.py | 290 +++ .../charms/squid/venv/jinja2/lexer.py | 848 ++++++++ .../charms/squid/venv/jinja2/loaders.py | 504 +++++ .../charms/squid/venv/jinja2/meta.py | 101 + .../charms/squid/venv/jinja2/nativetypes.py | 94 + .../charms/squid/venv/jinja2/nodes.py | 1088 ++++++++++ .../charms/squid/venv/jinja2/optimizer.py | 41 + .../charms/squid/venv/jinja2/parser.py | 939 +++++++++ .../charms/squid/venv/jinja2/runtime.py | 1011 +++++++++ .../charms/squid/venv/jinja2/sandbox.py | 510 +++++ .../charms/squid/venv/jinja2/tests.py | 215 ++ .../charms/squid/venv/jinja2/utils.py | 732 +++++++ .../charms/squid/venv/jinja2/visitor.py | 81 + .../charms/squid/venv/markupsafe/__init__.py | 327 +++ .../charms/squid/venv/markupsafe/_compat.py | 33 + .../squid/venv/markupsafe/_constants.py | 264 +++ .../charms/squid/venv/markupsafe/_native.py | 69 + .../charms/squid/venv/markupsafe/_speedups.c | 423 ++++ .../_speedups.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 48016 bytes .../venv/oci_image-1.0.0.dist-info/INSTALLER | 1 + .../venv/oci_image-1.0.0.dist-info/METADATA | 63 + .../venv/oci_image-1.0.0.dist-info/RECORD | 7 + .../venv/oci_image-1.0.0.dist-info/WHEEL | 5 + .../oci_image-1.0.0.dist-info/top_level.txt | 1 + .../squid_cnf/charms/squid/venv/oci_image.py | 53 + .../squid/venv/ops-1.1.0.dist-info/INSTALLER | 1 + .../ops-1.1.0.dist-info}/LICENSE.txt | 0 .../squid/venv/ops-1.1.0.dist-info/METADATA | 263 +++ .../squid/venv/ops-1.1.0.dist-info/RECORD | 28 + .../squid/venv/ops-1.1.0.dist-info/WHEEL | 5 + .../venv/ops-1.1.0.dist-info/top_level.txt | 1 + .../{mod/operator => venv}/ops/__init__.py | 4 +- .../squid_cnf/charms/squid/venv/ops/charm.py | 823 ++++++++ .../squid/{lib => venv}/ops/framework.py | 385 ++-- .../squid/{lib => venv}/ops/jujuversion.py | 29 + .../charms/squid/venv/ops/lib/__init__.py | 264 +++ .../charms/squid/{lib => venv}/ops/log.py | 11 + magma/squid_cnf/charms/squid/venv/ops/main.py | 406 ++++ .../charms/squid/{lib => venv}/ops/model.py | 621 +++++- .../charms/squid/venv/ops/storage.py | 374 ++++ .../charms/squid/{lib => venv}/ops/testing.py | 407 +++- .../charms/squid/venv/ops/version.py | 3 + .../charms/squid/venv/yaml/__init__.py | 427 ++++ .../charms/squid/venv/yaml/composer.py | 139 ++ .../charms/squid/venv/yaml/constructor.py | 748 +++++++ .../squid_cnf/charms/squid/venv/yaml/cyaml.py | 101 + .../charms/squid/venv/yaml/dumper.py | 62 + .../charms/squid/venv/yaml/emitter.py | 1137 ++++++++++ .../squid_cnf/charms/squid/venv/yaml/error.py | 75 + .../charms/squid/venv/yaml/events.py | 86 + .../charms/squid/venv/yaml/loader.py | 63 + .../squid_cnf/charms/squid/venv/yaml/nodes.py | 49 + .../charms/squid/venv/yaml/parser.py | 589 ++++++ .../charms/squid/venv/yaml/reader.py | 185 ++ .../charms/squid/venv/yaml/representer.py | 389 ++++ .../charms/squid/venv/yaml/resolver.py | 227 ++ .../charms/squid/venv/yaml/scanner.py | 1435 +++++++++++++ .../charms/squid/venv/yaml/serializer.py | 111 + .../charms/squid/venv/yaml/tokens.py | 104 + magma/squid_cnf/charms/squid_src/README.md | 47 + magma/squid_cnf/charms/squid_src/actions.yaml | 14 + magma/squid_cnf/charms/squid_src/config.yaml | 5 + .../squid_cnf/charms/squid_src/metadata.yaml | 24 + .../charms/squid_src/requirements.txt | 3 + magma/squid_cnf/charms/squid_src/squid.charm | Bin 0 -> 601730 bytes magma/squid_cnf/charms/squid_src/src/charm.py | 114 + .../charms/squid_src/template/squid.conf | 26 + .../tests/functional/requirements.txt | 1 + .../functional/tests/bundles/bionic.yaml | 6 + .../functional/tests/bundles/xenial.yaml | 7 + .../tests/functional/tests/tests.yaml | 17 + .../squid_src/tests/unit/operator_fixtures.py | 113 + .../squid_src/tests/unit/requirements.txt | 3 + .../src => squid_src/tests/unit}/setuppath.py | 0 .../charms/squid_src/tests/unit/test_charm.py | 19 + magma/squid_cnf/charms/squid_src/tox.ini | 46 + magma/squid_cnf/juju-bundles/bundle.yaml | 2 + 162 files changed, 24751 insertions(+), 10582 deletions(-) delete mode 100755 magma/squid_cnf/charms/squid/actions/addurl create mode 100755 magma/squid_cnf/charms/squid/dispatch create mode 120000 magma/squid_cnf/charms/squid/hooks/start create mode 120000 magma/squid_cnf/charms/squid/hooks/upgrade-charm delete mode 100644 magma/squid_cnf/charms/squid/lib/.empty delete mode 100644 magma/squid_cnf/charms/squid/lib/ops/__init__.py delete mode 100755 magma/squid_cnf/charms/squid/lib/ops/charm.py delete mode 100755 magma/squid_cnf/charms/squid/lib/ops/main.py delete mode 100644 magma/squid_cnf/charms/squid/mod/.empty delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.flake8 delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.gitignore delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.travis.yml delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/README.md delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/build_docs delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/docs/conf.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/docs/index.rst delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/charm.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/framework.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/ops/log.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/main.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/ops/model.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/ops/testing.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/requirements.txt delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/run_tests delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/setup.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/__init__.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/__init__.py delete mode 120000 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_log.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_main.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_model.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py create mode 100644 magma/squid_cnf/charms/squid/requirements.txt create mode 100644 magma/squid_cnf/charms/squid/squid.charm create mode 100644 magma/squid_cnf/charms/squid/template/squid.conf create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/LICENSE.rst create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/LICENSE create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/__init__.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/_compat.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/bccache.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/compiler.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/constants.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/debug.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/defaults.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/environment.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/exceptions.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/ext.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/filters.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/idtracking.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/lexer.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/loaders.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/meta.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/nativetypes.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/nodes.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/optimizer.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/parser.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/runtime.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/sandbox.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/tests.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/utils.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/visitor.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/__init__.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_compat.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_constants.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_native.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_speedups.c create mode 100755 magma/squid_cnf/charms/squid/venv/markupsafe/_speedups.cpython-38-x86_64-linux-gnu.so create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image.py create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/INSTALLER rename magma/squid_cnf/charms/squid/{mod/operator => venv/ops-1.1.0.dist-info}/LICENSE.txt (100%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/top_level.txt rename magma/squid_cnf/charms/squid/{mod/operator => venv}/ops/__init__.py (83%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/charm.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/framework.py (78%) mode change 100755 => 100644 rename magma/squid_cnf/charms/squid/{lib => venv}/ops/jujuversion.py (73%) mode change 100755 => 100644 create mode 100644 magma/squid_cnf/charms/squid/venv/ops/lib/__init__.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/log.py (79%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/main.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/model.py (57%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/storage.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/testing.py (51%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/version.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/__init__.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/composer.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/constructor.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/cyaml.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/dumper.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/emitter.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/error.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/events.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/loader.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/nodes.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/parser.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/reader.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/representer.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/resolver.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/scanner.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/serializer.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/tokens.py create mode 100644 magma/squid_cnf/charms/squid_src/README.md create mode 100644 magma/squid_cnf/charms/squid_src/actions.yaml create mode 100644 magma/squid_cnf/charms/squid_src/config.yaml create mode 100644 magma/squid_cnf/charms/squid_src/metadata.yaml create mode 100644 magma/squid_cnf/charms/squid_src/requirements.txt create mode 100644 magma/squid_cnf/charms/squid_src/squid.charm create mode 100755 magma/squid_cnf/charms/squid_src/src/charm.py create mode 100644 magma/squid_cnf/charms/squid_src/template/squid.conf create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/requirements.txt create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/tests/bundles/bionic.yaml create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/tests/bundles/xenial.yaml create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/tests/tests.yaml create mode 100644 magma/squid_cnf/charms/squid_src/tests/unit/operator_fixtures.py create mode 100644 magma/squid_cnf/charms/squid_src/tests/unit/requirements.txt rename magma/squid_cnf/charms/{squid/src => squid_src/tests/unit}/setuppath.py (100%) create mode 100644 magma/squid_cnf/charms/squid_src/tests/unit/test_charm.py create mode 100644 magma/squid_cnf/charms/squid_src/tox.ini diff --git a/magma/squid_cnf/charms/squid/actions/addurl b/magma/squid_cnf/charms/squid/actions/addurl deleted file mode 100755 index e12bf9fe..00000000 --- a/magma/squid_cnf/charms/squid/actions/addurl +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -URL=`action-get url` - -if ! grep -Fxq "http_access allow allowedurls" /etc/squid/squid.conf -then - sed -i '/^# And finally deny all .*/i http_access allow allowedurls\n' /etc/squid/squid.conf -fi - -sed -i "/^http_access allow allowedurls.*/i acl allowedurls dstdomain \.$URL" /etc/squid/squid.conf - -kill -HUP `cat /var/run/squid.pid` - diff --git a/magma/squid_cnf/charms/squid/config.yaml b/magma/squid_cnf/charms/squid/config.yaml index 65c33a86..450525ee 100644 --- a/magma/squid_cnf/charms/squid/config.yaml +++ b/magma/squid_cnf/charms/squid/config.yaml @@ -1,9 +1,5 @@ options: - image: - type: string - description: 'Docker image for squid' - default: 'domfleischmann/squid-python' port: type: int - description: 'Port' + description: "Port" default: 3128 diff --git a/magma/squid_cnf/charms/squid/dispatch b/magma/squid_cnf/charms/squid/dispatch new file mode 100755 index 00000000..fe31c056 --- /dev/null +++ b/magma/squid_cnf/charms/squid/dispatch @@ -0,0 +1,3 @@ +#!/bin/sh + +JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py diff --git a/magma/squid_cnf/charms/squid/hooks/install b/magma/squid_cnf/charms/squid/hooks/install index 25b1f68f..8b970447 120000 --- a/magma/squid_cnf/charms/squid/hooks/install +++ b/magma/squid_cnf/charms/squid/hooks/install @@ -1 +1 @@ -../src/charm.py \ No newline at end of file +../dispatch \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/hooks/start b/magma/squid_cnf/charms/squid/hooks/start new file mode 120000 index 00000000..8b970447 --- /dev/null +++ b/magma/squid_cnf/charms/squid/hooks/start @@ -0,0 +1 @@ +../dispatch \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/hooks/upgrade-charm b/magma/squid_cnf/charms/squid/hooks/upgrade-charm new file mode 120000 index 00000000..8b970447 --- /dev/null +++ b/magma/squid_cnf/charms/squid/hooks/upgrade-charm @@ -0,0 +1 @@ +../dispatch \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/lib/.empty b/magma/squid_cnf/charms/squid/lib/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/lib/ops/__init__.py b/magma/squid_cnf/charms/squid/lib/ops/__init__.py deleted file mode 100644 index b2089e38..00000000 --- a/magma/squid_cnf/charms/squid/lib/ops/__init__.py +++ /dev/null @@ -1,18 +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. - -"""The Operator Framework.""" - -# Import here the bare minimum to break the circular import between modules -from . import charm # NOQA diff --git a/magma/squid_cnf/charms/squid/lib/ops/charm.py b/magma/squid_cnf/charms/squid/lib/ops/charm.py deleted file mode 100755 index 4682c20e..00000000 --- a/magma/squid_cnf/charms/squid/lib/ops/charm.py +++ /dev/null @@ -1,562 +0,0 @@ -# Copyright 2019-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. - -import os -import pathlib -import typing - -import yaml - -from ops.framework import Object, EventSource, EventBase, Framework, ObjectEvents -from ops import model - - -class HookEvent(EventBase): - """A base class for events that trigger because of a Juju hook firing.""" - - -class ActionEvent(EventBase): - """A base class for events that trigger when a user asks for an Action to be run. - - To read the parameters for the action, see the instance variable `params`. - To respond with the result of the action, call `set_results`. To add progress - messages that are visible as the action is progressing use `log`. - - :ivar params: The parameters passed to the action (read by action-get) - """ - - def defer(self): - """Action events are not deferable like other events. - - This is because an action runs synchronously and the user is waiting for the result. - """ - raise RuntimeError('cannot defer action events') - - def restore(self, snapshot: dict) -> None: - """Used by the operator framework to record the action. - - Not meant to be called directly by Charm code. - """ - env_action_name = os.environ.get('JUJU_ACTION_NAME') - event_action_name = self.handle.kind[:-len('_action')].replace('_', '-') - if event_action_name != env_action_name: - # This could only happen if the dev manually emits the action, or from a bug. - raise RuntimeError('action event kind does not match current action') - # Params are loaded at restore rather than __init__ because - # the model is not available in __init__. - self.params = self.framework.model._backend.action_get() - - def set_results(self, results: typing.Mapping) -> None: - """Report the result of the action. - - Args: - results: The result of the action as a Dict - """ - self.framework.model._backend.action_set(results) - - def log(self, message: str) -> None: - """Send a message that a user will see while the action is running. - - Args: - message: The message for the user. - """ - self.framework.model._backend.action_log(message) - - def fail(self, message: str = '') -> None: - """Report that this action has failed. - - Args: - message: Optional message to record why it has failed. - """ - self.framework.model._backend.action_fail(message) - - -class InstallEvent(HookEvent): - """Represents the `install` hook from Juju.""" - - -class StartEvent(HookEvent): - """Represents the `start` hook from Juju.""" - - -class StopEvent(HookEvent): - """Represents the `stop` hook from Juju.""" - - -class RemoveEvent(HookEvent): - """Represents the `remove` hook from Juju. """ - - -class ConfigChangedEvent(HookEvent): - """Represents the `config-changed` hook from Juju.""" - - -class UpdateStatusEvent(HookEvent): - """Represents the `update-status` hook from Juju.""" - - -class UpgradeCharmEvent(HookEvent): - """Represents the `upgrade-charm` hook from Juju. - - This will be triggered when a user has run `juju upgrade-charm`. It is run after Juju - has unpacked the upgraded charm code, and so this event will be handled with new code. - """ - - -class PreSeriesUpgradeEvent(HookEvent): - """Represents the `pre-series-upgrade` hook from Juju. - - This happens when a user has run `juju upgrade-series MACHINE prepare` and - will fire for each unit that is running on the machine, telling them that - the user is preparing to upgrade the Machine's series (eg trusty->bionic). - The charm should take actions to prepare for the upgrade (a database charm - would want to write out a version-independent dump of the database, so that - when a new version of the database is available in a new series, it can be - used.) - Once all units on a machine have run `pre-series-upgrade`, the user will - initiate the steps to actually upgrade the machine (eg `do-release-upgrade`). - When the upgrade has been completed, the :class:`PostSeriesUpgradeEvent` will fire. - """ - - -class PostSeriesUpgradeEvent(HookEvent): - """Represents the `post-series-upgrade` hook from Juju. - - This is run after the user has done a distribution upgrade (or rolled back - and kept the same series). It is called in response to - `juju upgrade-series MACHINE complete`. Charms are expected to do whatever - steps are necessary to reconfigure their applications for the new series. - """ - - -class LeaderElectedEvent(HookEvent): - """Represents the `leader-elected` hook from Juju. - - Juju will trigger this when a new lead unit is chosen for a given application. - This represents the leader of the charm information (not necessarily the primary - of a running application). The main utility is that charm authors can know - that only one unit will be a leader at any given time, so they can do - configuration, etc, that would otherwise require coordination between units. - (eg, selecting a password for a new relation) - """ - - -class LeaderSettingsChangedEvent(HookEvent): - """Represents the `leader-settings-changed` hook from Juju. - - Deprecated. This represents when a lead unit would call `leader-set` to inform - the other units of an application that they have new information to handle. - This has been deprecated in favor of using a Peer relation, and having the - leader set a value in the Application data bag for that peer relation. - (see :class:`RelationChangedEvent`). - """ - - -class CollectMetricsEvent(HookEvent): - """Represents the `collect-metrics` hook from Juju. - - Note that events firing during a CollectMetricsEvent are currently - sandboxed in how they can interact with Juju. To report metrics - use :meth:`.add_metrics`. - """ - - def add_metrics(self, metrics: typing.Mapping, labels: typing.Mapping = None) -> None: - """Record metrics that have been gathered by the charm for this unit. - - Args: - metrics: A collection of {key: float} pairs that contains the - metrics that have been gathered - labels: {key:value} strings that can be applied to the - metrics that are being gathered - """ - self.framework.model._backend.add_metrics(metrics, labels) - - -class RelationEvent(HookEvent): - """A base class representing the various relation lifecycle events. - - Charmers should not be creating RelationEvents directly. The events will be - generated by the framework from Juju related events. Users can observe them - from the various `CharmBase.on[relation_name].relation_*` events. - - Attributes: - relation: The Relation involved in this event - app: The remote application that has triggered this event - unit: The remote unit that has triggered this event. This may be None - if the relation event was triggered as an Application level event - """ - - def __init__(self, handle, relation, app=None, unit=None): - super().__init__(handle) - - if unit is not None and unit.app != app: - raise RuntimeError( - 'cannot create RelationEvent with application {} and unit {}'.format(app, unit)) - - self.relation = relation - self.app = app - self.unit = unit - - def snapshot(self) -> dict: - """Used by the framework to serialize the event to disk. - - Not meant to be called by Charm code. - """ - snapshot = { - 'relation_name': self.relation.name, - 'relation_id': self.relation.id, - } - if self.app: - snapshot['app_name'] = self.app.name - if self.unit: - snapshot['unit_name'] = self.unit.name - return snapshot - - def restore(self, snapshot: dict) -> None: - """Used by the framework to deserialize the event from disk. - - Not meant to be called by Charm code. - """ - self.relation = self.framework.model.get_relation( - snapshot['relation_name'], snapshot['relation_id']) - - app_name = snapshot.get('app_name') - if app_name: - self.app = self.framework.model.get_app(app_name) - else: - self.app = None - - unit_name = snapshot.get('unit_name') - if unit_name: - self.unit = self.framework.model.get_unit(unit_name) - else: - self.unit = None - - -class RelationCreatedEvent(RelationEvent): - """Represents the `relation-created` hook from Juju. - - This is triggered when a new relation to another app is added in Juju. This - can occur before units for those applications have started. All existing - relations should be established before start. - """ - - -class RelationJoinedEvent(RelationEvent): - """Represents the `relation-joined` hook from Juju. - - This is triggered whenever a new unit of a related application joins the relation. - (eg, a unit was added to an existing related app, or a new relation was established - with an application that already had units.) - """ - - -class RelationChangedEvent(RelationEvent): - """Represents the `relation-changed` hook from Juju. - - This is triggered whenever there is a change to the data bucket for a related - application or unit. Look at `event.relation.data[event.unit/app]` to see the - new information. - """ - - -class RelationDepartedEvent(RelationEvent): - """Represents the `relation-departed` hook from Juju. - - This is the inverse of the RelationJoinedEvent, representing when a unit - is leaving the relation (the unit is being removed, the app is being removed, - the relation is being removed). It is fired once for each unit that is - going away. - """ - - -class RelationBrokenEvent(RelationEvent): - """Represents the `relation-broken` hook from Juju. - - If a relation is being removed (`juju remove-relation` or `juju remove-application`), - once all the units have been removed, RelationBrokenEvent will fire to signal - that the relationship has been fully terminated. - """ - - -class StorageEvent(HookEvent): - """Base class representing Storage related events.""" - - -class StorageAttachedEvent(StorageEvent): - """Represents the `storage-attached` hook from Juju. - - Called when new storage is available for the charm to use. - """ - - -class StorageDetachingEvent(StorageEvent): - """Represents the `storage-detaching` hook from Juju. - - Called when storage a charm has been using is going away. - """ - - -class CharmEvents(ObjectEvents): - """The events that are generated by Juju in response to the lifecycle of an application.""" - - install = EventSource(InstallEvent) - start = EventSource(StartEvent) - stop = EventSource(StopEvent) - remove = EventSource(RemoveEvent) - update_status = EventSource(UpdateStatusEvent) - config_changed = EventSource(ConfigChangedEvent) - upgrade_charm = EventSource(UpgradeCharmEvent) - pre_series_upgrade = EventSource(PreSeriesUpgradeEvent) - post_series_upgrade = EventSource(PostSeriesUpgradeEvent) - leader_elected = EventSource(LeaderElectedEvent) - leader_settings_changed = EventSource(LeaderSettingsChangedEvent) - collect_metrics = EventSource(CollectMetricsEvent) - - -class CharmBase(Object): - """Base class that represents the Charm overall. - - Usually this initialization is done by ops.main.main() rather than Charm authors - directly instantiating a Charm. - - Args: - framework: The framework responsible for managing the Model and events for this - Charm. - key: Arbitrary key to distinguish this instance of CharmBase from another. - Generally is None when initialized by the framework. For charms instantiated by - main.main(), this is currenly None. - Attributes: - on: Defines all events that the Charm will fire. - """ - - on = CharmEvents() - - def __init__(self, framework: Framework, key: typing.Optional[str]): - """Initialize the Charm with its framework and application name. - - """ - super().__init__(framework, key) - - for relation_name in self.framework.meta.relations: - relation_name = relation_name.replace('-', '_') - self.on.define_event(relation_name + '_relation_created', RelationCreatedEvent) - self.on.define_event(relation_name + '_relation_joined', RelationJoinedEvent) - self.on.define_event(relation_name + '_relation_changed', RelationChangedEvent) - self.on.define_event(relation_name + '_relation_departed', RelationDepartedEvent) - self.on.define_event(relation_name + '_relation_broken', RelationBrokenEvent) - - for storage_name in self.framework.meta.storages: - storage_name = storage_name.replace('-', '_') - self.on.define_event(storage_name + '_storage_attached', StorageAttachedEvent) - self.on.define_event(storage_name + '_storage_detaching', StorageDetachingEvent) - - for action_name in self.framework.meta.actions: - action_name = action_name.replace('-', '_') - self.on.define_event(action_name + '_action', ActionEvent) - - @property - def app(self) -> model.Application: - """Application that this unit is part of.""" - return self.framework.model.app - - @property - def unit(self) -> model.Unit: - """Unit that this execution is responsible for.""" - return self.framework.model.unit - - @property - def meta(self) -> 'CharmMeta': - """CharmMeta of this charm. - """ - return self.framework.meta - - @property - def charm_dir(self) -> pathlib.Path: - """Root directory of the Charm as it is running. - """ - return self.framework.charm_dir - - -class CharmMeta: - """Object containing the metadata for the charm. - - This is read from metadata.yaml and/or actions.yaml. Generally charms will - define this information, rather than reading it at runtime. This class is - mostly for the framework to understand what the charm has defined. - - The maintainers, tags, terms, series, and extra_bindings attributes are all - lists of strings. The requires, provides, peers, relations, storage, - resources, and payloads attributes are all mappings of names to instances - of the respective RelationMeta, StorageMeta, ResourceMeta, or PayloadMeta. - - The relations attribute is a convenience accessor which includes all of the - requires, provides, and peers RelationMeta items. If needed, the role of - the relation definition can be obtained from its role attribute. - - Attributes: - name: The name of this charm - summary: Short description of what this charm does - description: Long description for this charm - maintainers: A list of strings of the email addresses of the maintainers - of this charm. - tags: Charm store tag metadata for categories associated with this charm. - terms: Charm store terms that should be agreed to before this charm can - be deployed. (Used for things like licensing issues.) - series: The list of supported OS series that this charm can support. - The first entry in the list is the default series that will be - used by deploy if no other series is requested by the user. - subordinate: True/False whether this charm is intended to be used as a - subordinate charm. - min_juju_version: If supplied, indicates this charm needs features that - are not available in older versions of Juju. - requires: A dict of {name: :class:`RelationMeta` } for each 'requires' relation. - provides: A dict of {name: :class:`RelationMeta` } for each 'provides' relation. - peers: A dict of {name: :class:`RelationMeta` } for each 'peer' relation. - relations: A dict containing all :class:`RelationMeta` attributes (merged from other - sections) - storages: A dict of {name: :class:`StorageMeta`} for each defined storage. - resources: A dict of {name: :class:`ResourceMeta`} for each defined resource. - payloads: A dict of {name: :class:`PayloadMeta`} for each defined payload. - extra_bindings: A dict of additional named bindings that a charm can use - for network configuration. - actions: A dict of {name: :class:`ActionMeta`} for actions that the charm has defined. - Args: - raw: a mapping containing the contents of metadata.yaml - actions_raw: a mapping containing the contents of actions.yaml - """ - - def __init__(self, raw: dict = {}, actions_raw: dict = {}): - self.name = raw.get('name', '') - self.summary = raw.get('summary', '') - self.description = raw.get('description', '') - self.maintainers = [] - if 'maintainer' in raw: - self.maintainers.append(raw['maintainer']) - if 'maintainers' in raw: - self.maintainers.extend(raw['maintainers']) - self.tags = raw.get('tags', []) - self.terms = raw.get('terms', []) - self.series = raw.get('series', []) - self.subordinate = raw.get('subordinate', False) - self.min_juju_version = raw.get('min-juju-version') - self.requires = {name: RelationMeta('requires', name, rel) - for name, rel in raw.get('requires', {}).items()} - self.provides = {name: RelationMeta('provides', name, rel) - for name, rel in raw.get('provides', {}).items()} - # TODO: (jam 2020-05-11) The *role* should be 'peer' even though it comes from the - # 'peers' section. - self.peers = {name: RelationMeta('peers', name, rel) - for name, rel in raw.get('peers', {}).items()} - self.relations = {} - self.relations.update(self.requires) - self.relations.update(self.provides) - self.relations.update(self.peers) - self.storages = {name: StorageMeta(name, storage) - for name, storage in raw.get('storage', {}).items()} - self.resources = {name: ResourceMeta(name, res) - for name, res in raw.get('resources', {}).items()} - self.payloads = {name: PayloadMeta(name, payload) - for name, payload in raw.get('payloads', {}).items()} - self.extra_bindings = raw.get('extra-bindings', {}) - self.actions = {name: ActionMeta(name, action) for name, action in actions_raw.items()} - - @classmethod - def from_yaml( - cls, metadata: typing.Union[str, typing.TextIO], - actions: typing.Optional[typing.Union[str, typing.TextIO]] = None): - """Instantiate a CharmMeta from a YAML description of metadata.yaml. - - Args: - metadata: A YAML description of charm metadata (name, relations, etc.) - This can be a simple string, or a file-like object. (passed to `yaml.safe_load`). - actions: YAML description of Actions for this charm (eg actions.yaml) - """ - meta = yaml.safe_load(metadata) - raw_actions = {} - if actions is not None: - raw_actions = yaml.safe_load(actions) - return cls(meta, raw_actions) - - -class RelationMeta: - """Object containing metadata about a relation definition. - - Should not be constructed directly by Charm code. Is gotten from one of - :attr:`CharmMeta.peers`, :attr:`CharmMeta.requires`, :attr:`CharmMeta.provides`, - :attr:`CharmMeta.relations`. - - Attributes: - role: This is one of requires/provides/peers - relation_name: Name of this relation from metadata.yaml - interface_name: Optional definition of the interface protocol. - scope: "global" or "container" scope based on how the relation should be used. - """ - - def __init__(self, role, relation_name, raw): - self.role = role - self.relation_name = relation_name - self.interface_name = raw['interface'] - self.scope = raw.get('scope') - - -class StorageMeta: - """Object containing metadata about a storage definition.""" - - def __init__(self, name, raw): - self.storage_name = name - self.type = raw['type'] - self.description = raw.get('description', '') - self.shared = raw.get('shared', False) - self.read_only = raw.get('read-only', False) - self.minimum_size = raw.get('minimum-size') - self.location = raw.get('location') - self.multiple_range = None - if 'multiple' in raw: - range = raw['multiple']['range'] - if '-' not in range: - self.multiple_range = (int(range), int(range)) - else: - range = range.split('-') - self.multiple_range = (int(range[0]), int(range[1]) if range[1] else None) - - -class ResourceMeta: - """Object containing metadata about a resource definition.""" - - def __init__(self, name, raw): - self.resource_name = name - self.type = raw['type'] - self.filename = raw.get('filename', None) - self.description = raw.get('description', '') - - -class PayloadMeta: - """Object containing metadata about a payload definition.""" - - def __init__(self, name, raw): - self.payload_name = name - self.type = raw['type'] - - -class ActionMeta: - """Object containing metadata about an action's definition.""" - - def __init__(self, name, raw=None): - raw = raw or {} - self.name = name - self.title = raw.get('title', '') - self.description = raw.get('description', '') - self.parameters = raw.get('params', {}) # {: } - self.required = raw.get('required', []) # [, ...] diff --git a/magma/squid_cnf/charms/squid/lib/ops/main.py b/magma/squid_cnf/charms/squid/lib/ops/main.py deleted file mode 100755 index 0f5391d7..00000000 --- a/magma/squid_cnf/charms/squid/lib/ops/main.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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. - -import os -import subprocess -import sys -from pathlib import Path - -import yaml - -import ops.charm -import ops.framework -import ops.model -import logging - -from ops.log import setup_root_logging - -CHARM_STATE_FILE = '.unit-state.db' - - -logger = logging.getLogger() - - -def _get_charm_dir(): - charm_dir = os.environ.get("JUJU_CHARM_DIR") - if charm_dir is None: - # Assume $JUJU_CHARM_DIR/lib/op/main.py structure. - charm_dir = Path('{}/../../..'.format(__file__)).resolve() - else: - charm_dir = Path(charm_dir).resolve() - return charm_dir - - -def _load_metadata(charm_dir): - metadata = yaml.safe_load((charm_dir / 'metadata.yaml').read_text()) - - actions_meta = charm_dir / 'actions.yaml' - if actions_meta.exists(): - actions_metadata = yaml.safe_load(actions_meta.read_text()) - else: - actions_metadata = {} - return metadata, actions_metadata - - -def _create_event_link(charm, bound_event): - """Create a symlink for a particular event. - - charm -- A charm object. - bound_event -- An event for which to create a symlink. - """ - if issubclass(bound_event.event_type, ops.charm.HookEvent): - event_dir = charm.framework.charm_dir / 'hooks' - event_path = event_dir / bound_event.event_kind.replace('_', '-') - elif issubclass(bound_event.event_type, ops.charm.ActionEvent): - if not bound_event.event_kind.endswith("_action"): - raise RuntimeError( - 'action event name {} needs _action suffix'.format(bound_event.event_kind)) - event_dir = charm.framework.charm_dir / 'actions' - # The event_kind is suffixed with "_action" while the executable is not. - event_path = event_dir / bound_event.event_kind[:-len('_action')].replace('_', '-') - else: - raise RuntimeError( - 'cannot create a symlink: unsupported event type {}'.format(bound_event.event_type)) - - event_dir.mkdir(exist_ok=True) - if not event_path.exists(): - # CPython has different implementations for populating sys.argv[0] for Linux and Windows. - # For Windows it is always an absolute path (any symlinks are resolved) - # while for Linux it can be a relative path. - target_path = os.path.relpath(os.path.realpath(sys.argv[0]), str(event_dir)) - - # Ignore the non-symlink files or directories - # assuming the charm author knows what they are doing. - logger.debug( - 'Creating a new relative symlink at %s pointing to %s', - event_path, target_path) - event_path.symlink_to(target_path) - - -def _setup_event_links(charm_dir, charm): - """Set up links for supported events that originate from Juju. - - Whether a charm can handle an event or not can be determined by - introspecting which events are defined on it. - - Hooks or actions are created as symlinks to the charm code file - which is determined by inspecting symlinks provided by the charm - author at hooks/install or hooks/start. - - charm_dir -- A root directory of the charm. - charm -- An instance of the Charm class. - - """ - for bound_event in charm.on.events().values(): - # Only events that originate from Juju need symlinks. - if issubclass(bound_event.event_type, (ops.charm.HookEvent, ops.charm.ActionEvent)): - _create_event_link(charm, bound_event) - - -def _emit_charm_event(charm, event_name): - """Emits a charm event based on a Juju event name. - - charm -- A charm instance to emit an event from. - event_name -- A Juju event name to emit on a charm. - """ - event_to_emit = None - try: - event_to_emit = getattr(charm.on, event_name) - except AttributeError: - logger.debug("event %s not defined for %s", event_name, charm) - - # If the event is not supported by the charm implementation, do - # not error out or try to emit it. This is to support rollbacks. - if event_to_emit is not None: - args, kwargs = _get_event_args(charm, event_to_emit) - logger.debug('Emitting Juju event %s', event_name) - event_to_emit.emit(*args, **kwargs) - - -def _get_event_args(charm, bound_event): - event_type = bound_event.event_type - model = charm.framework.model - - if issubclass(event_type, ops.charm.RelationEvent): - relation_name = os.environ['JUJU_RELATION'] - relation_id = int(os.environ['JUJU_RELATION_ID'].split(':')[-1]) - relation = model.get_relation(relation_name, relation_id) - else: - relation = None - - remote_app_name = os.environ.get('JUJU_REMOTE_APP', '') - remote_unit_name = os.environ.get('JUJU_REMOTE_UNIT', '') - if remote_app_name or remote_unit_name: - if not remote_app_name: - if '/' not in remote_unit_name: - raise RuntimeError('invalid remote unit name: {}'.format(remote_unit_name)) - remote_app_name = remote_unit_name.split('/')[0] - args = [relation, model.get_app(remote_app_name)] - if remote_unit_name: - args.append(model.get_unit(remote_unit_name)) - return args, {} - elif relation: - return [relation], {} - return [], {} - - -def main(charm_class): - """Setup the charm and dispatch the observed event. - - The event name is based on the way this executable was called (argv[0]). - """ - charm_dir = _get_charm_dir() - - model_backend = ops.model.ModelBackend() - debug = ('JUJU_DEBUG' in os.environ) - setup_root_logging(model_backend, debug=debug) - - # Process the Juju event relevant to the current hook execution - # JUJU_HOOK_NAME, JUJU_FUNCTION_NAME, and JUJU_ACTION_NAME are not used - # in order to support simulation of events from debugging sessions. - # - # TODO: For Windows, when symlinks are used, this is not a valid - # method of getting an event name (see LP: #1854505). - juju_exec_path = Path(sys.argv[0]) - has_dispatch = juju_exec_path.name == 'dispatch' - if has_dispatch: - # The executable was 'dispatch', which means the actual hook we want to - # run needs to be looked up in the JUJU_DISPATCH_PATH env var, where it - # should be a path relative to the charm directory (the directory that - # holds `dispatch`). If that path actually exists, we want to run that - # before continuing. - dispatch_path = juju_exec_path.parent / Path(os.environ['JUJU_DISPATCH_PATH']) - if dispatch_path.exists() and dispatch_path.resolve() != juju_exec_path.resolve(): - argv = sys.argv.copy() - argv[0] = str(dispatch_path) - try: - subprocess.run(argv, check=True) - except subprocess.CalledProcessError as e: - logger.warning("hook %s exited with status %d", dispatch_path, e.returncode) - sys.exit(e.returncode) - juju_exec_path = dispatch_path - juju_event_name = juju_exec_path.name.replace('-', '_') - if juju_exec_path.parent.name == 'actions': - juju_event_name = '{}_action'.format(juju_event_name) - - metadata, actions_metadata = _load_metadata(charm_dir) - meta = ops.charm.CharmMeta(metadata, actions_metadata) - unit_name = os.environ['JUJU_UNIT_NAME'] - model = ops.model.Model(unit_name, meta, model_backend) - - # TODO: If Juju unit agent crashes after exit(0) from the charm code - # the framework will commit the snapshot but Juju will not commit its - # operation. - charm_state_path = charm_dir / CHARM_STATE_FILE - framework = ops.framework.Framework(charm_state_path, charm_dir, meta, model) - try: - charm = charm_class(framework, None) - - if not has_dispatch: - # When a charm is force-upgraded and a unit is in an error state Juju - # does not run upgrade-charm and instead runs the failed hook followed - # by config-changed. Given the nature of force-upgrading the hook setup - # code is not triggered on config-changed. - # - # 'start' event is included as Juju does not fire the install event for - # K8s charms (see LP: #1854635). - if (juju_event_name in ('install', 'start', 'upgrade_charm') - or juju_event_name.endswith('_storage_attached')): - _setup_event_links(charm_dir, charm) - - # TODO: Remove the collect_metrics check below as soon as the relevant - # Juju changes are made. - # - # Skip reemission of deferred events for collect-metrics events because - # they do not have the full access to all hook tools. - if juju_event_name != 'collect_metrics': - framework.reemit() - - _emit_charm_event(charm, juju_event_name) - - framework.commit() - finally: - framework.close() diff --git a/magma/squid_cnf/charms/squid/metadata.yaml b/magma/squid_cnf/charms/squid/metadata.yaml index aa3bbfa1..aabf09bc 100644 --- a/magma/squid_cnf/charms/squid/metadata.yaml +++ b/magma/squid_cnf/charms/squid/metadata.yaml @@ -14,10 +14,11 @@ deployment: type: stateful service: loadbalancer storage: - docker: - type: filesystem - location: /srv/docker/squid spool: type: filesystem location: /var/spool/squid - +resources: + image: + type: oci-image + description: OSM docker image for LCM + upstream-source: "domfleischmann/squid-python" \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/mod/.empty b/magma/squid_cnf/charms/squid/mod/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/mod/operator/.flake8 b/magma/squid_cnf/charms/squid/mod/operator/.flake8 deleted file mode 100644 index 61d90815..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -max-line-length = 99 diff --git a/magma/squid_cnf/charms/squid/mod/operator/.gitignore b/magma/squid_cnf/charms/squid/mod/operator/.gitignore deleted file mode 100644 index 5596c502..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -__pycache__ -/sandbox -.idea -docs/_build diff --git a/magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml b/magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml deleted file mode 100644 index ee5cf263..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: 2 # required -formats: [] # i.e. no extra formats (for now) -python: - version: "3.5" - install: - - requirements: docs/requirements.txt - - requirements: requirements.txt diff --git a/magma/squid_cnf/charms/squid/mod/operator/.travis.yml b/magma/squid_cnf/charms/squid/mod/operator/.travis.yml deleted file mode 100644 index f222ba8b..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -dist: bionic - -language: python - -arch: - - amd64 - - arm64 - -python: - - "3.5" - - "3.6" - - "3.7" - - "3.8" - -matrix: - include: - - os: osx - language: generic - -install: - - pip3 install pyyaml autopep8 flake8 - -script: - - ./run_tests diff --git a/magma/squid_cnf/charms/squid/mod/operator/README.md b/magma/squid_cnf/charms/squid/mod/operator/README.md deleted file mode 100644 index 347bfc8e..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/README.md +++ /dev/null @@ -1,137 +0,0 @@ -# The Operator Framework - -The Operator Framework provides a simple, lightweight, and powerful way of encapsulating operational experience in code. - -The framework will help you to: - -* model the integration of your services -* manage the lifecycle of your application -* create reusable and scalable components -* keep your code simple and readable - -## Getting Started - -The following overall structure for your charm directory is recommended: - -``` -. -├── config.yaml -├── metadata.yaml -├── mod/ -├── lib/ -│ └── ops -> ../mod/operator/ops -├── src/ -│ └── charm.py -└── hooks/ - ├── install -> ../src/charm.py - └── start -> ../src/charm.py # for k8s charms per below -``` - -The `mod/` directory should contain the operator framework dependency as a git -submodule: - -``` -git submodule add https://github.com/canonical/operator mod/operator -``` - -Then symlink from the git submodule for the operator framework into the `lib/` -directory of your charm so it can be imported at run time: - -``` -ln -s ../mod/operator/ops lib/ops -``` - -Other dependencies included as git submodules can be added in the `mod/` -directory and symlinked into `lib/` as well. - -You can sync subsequent changes from the framework and other submodule -dependencies by running: - -``` -git submodule update -``` - -Those cloning and checking out the source for your charm for the first time -will need to run: - -``` -git submodule update --init -``` - -Your `src/charm.py` is the entry point for your charm logic. It should be set -to executable and use Python 3.6 or greater. At a minimum, it needs to define -a subclass of `CharmBase` and pass that into the framework's `main` function: - -```python -import sys -sys.path.append('lib') # noqa: E402 - -from ops.charm import CharmBase -from ops.main import main - - -class MyCharm(CharmBase): - pass - - -if __name__ == "__main__": - main(MyCharm) -``` - -This charm does nothing, because the `MyCharm` class passed to the operator -framework's `main` function is empty. Functionality can be added to the charm -by instructing it to observe particular Juju events when the `MyCharm` object -is initialized. For example, - -```python -class MyCharm(CharmBase): - def __init__(self, *args): - super().__init__(*args) - self.framework.observe(self.on.start, self.on_start) - - def on_start(self, event): - # Handle the start event here. -``` - -Every standard event in Juju may be observed that way, and you can also easily -define your own events in your custom types. - -> The second argument to `observe` can be either the handler as a bound -> method, or the observer itself if the handler is a method of the observer -> that follows the conventional naming pattern. That is, in this case, we -> could have called just `self.framework.observe(self.on.start, self)`. - -The `hooks/` directory must contain a symlink to your `src/charm.py` entry -point so that Juju can call it. You only need to set up the `hooks/install` link -(`hooks/start` for K8s charms, until [lp#1854635](https://bugs.launchpad.net/juju/+bug/1854635) -is resolved), and the framework will create all others at runtime. - -Once your charm is ready, upload it to the charm store and deploy it as -normal with: - -``` -# Replace ${CHARM} with the name of the charm. -charm push . cs:~${USER}/${CHARM} -# Replace ${VERSION} with the version created by `charm push`. -charm release cs:~${USER}/${CHARM}-${VERSION} -charm grant cs:~${USER}/${CHARM}-${VERSION} everyone -# And now deploy your charm. -juju deploy cs:~${USER}/$CHARM -``` - -Alternatively, to deploy directly from local disk, run: - -``` -juju deploy . -``` - -# Operator Framework development - -If you want to work in the framework *itself* you will need the following depenencies installed in your system: - -- Python >= 3.5 -- PyYAML -- autopep8 -- flake8 - -Then you can try `./run_tests`, it should all go green. diff --git a/magma/squid_cnf/charms/squid/mod/operator/build_docs b/magma/squid_cnf/charms/squid/mod/operator/build_docs deleted file mode 100755 index af8b892f..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/build_docs +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -set -e - -flavour=html - -if [ "$1" ]; then - if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then - flavour=help - else - flavour="$1" - fi - shift -fi - -cd docs - -sphinx-build -M "$flavour" . _build "$@" diff --git a/magma/squid_cnf/charms/squid/mod/operator/docs/conf.py b/magma/squid_cnf/charms/squid/mod/operator/docs/conf.py deleted file mode 100644 index bd78ed2a..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/docs/conf.py +++ /dev/null @@ -1,89 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For a full list of options see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - - -# -- Path setup -------------------------------------------------------------- - -from pathlib import Path -import sys -sys.path.insert(0, str(Path(__file__).parent.parent)) - - -# -- Project information ----------------------------------------------------- - -project = 'The Operator Framework' -copyright = '2019-2020, Canonical Ltd.' -author = 'Canonical Ltd' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.todo', - 'sphinx.ext.viewcode', -] - -# The document name of the “master” document, that is, the document -# that contains the root toctree directive. -master_doc = 'index' - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -# html_theme = 'nature' # 'alabaster' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - - -# -- Options for sphinx.ext.todo --------------------------------------------- - -# If this is True, todo and todolist produce output, else they -# produce nothing. The default is False. -todo_include_todos = False - - -# -- Options for sphinx.ext.autodoc ------------------------------------------ - -# This value controls how to represents typehints. The setting takes the -# following values: -# 'signature' – Show typehints as its signature (default) -# 'description' – Show typehints as content of function or method -# 'none' – Do not show typehints -autodoc_typehints = 'description' - -# This value selects what content will be inserted into the main body of an -# autoclass directive. The possible values are: -# 'class' - Only the class’ docstring is inserted. This is the -# default. You can still document __init__ as a separate method -# using automethod or the members option to autoclass. -# 'both' - Both the class’ and the __init__ method’s docstring are -# concatenated and inserted. -# 'init' - Only the __init__ method’s docstring is inserted. -autoclass_content = 'both' - -autodoc_default_options = { - 'members': None, # None here means "yes" - 'undoc-members': None, - 'show-inheritance': None, -} diff --git a/magma/squid_cnf/charms/squid/mod/operator/docs/index.rst b/magma/squid_cnf/charms/squid/mod/operator/docs/index.rst deleted file mode 100644 index 424d78d4..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/docs/index.rst +++ /dev/null @@ -1,58 +0,0 @@ - -Welcome to The Operator Framework's documentation! -================================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - -ops package -=========== - -.. automodule:: ops - -Submodules ----------- - -ops.charm module ----------------- - -.. automodule:: ops.charm - -ops.framework module --------------------- - -.. automodule:: ops.framework - -ops.jujuversion module ----------------------- - -.. automodule:: ops.jujuversion - -ops.log module --------------- - -.. automodule:: ops.log - -ops.main module ---------------- - -.. automodule:: ops.main - -ops.model module ----------------- - -.. automodule:: ops.model - -ops.testing module ------------------- - -.. automodule:: ops.testing - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt b/magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt deleted file mode 100644 index 37b11036..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -sphinx<2 diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/charm.py b/magma/squid_cnf/charms/squid/mod/operator/ops/charm.py deleted file mode 100755 index 4682c20e..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/charm.py +++ /dev/null @@ -1,562 +0,0 @@ -# Copyright 2019-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. - -import os -import pathlib -import typing - -import yaml - -from ops.framework import Object, EventSource, EventBase, Framework, ObjectEvents -from ops import model - - -class HookEvent(EventBase): - """A base class for events that trigger because of a Juju hook firing.""" - - -class ActionEvent(EventBase): - """A base class for events that trigger when a user asks for an Action to be run. - - To read the parameters for the action, see the instance variable `params`. - To respond with the result of the action, call `set_results`. To add progress - messages that are visible as the action is progressing use `log`. - - :ivar params: The parameters passed to the action (read by action-get) - """ - - def defer(self): - """Action events are not deferable like other events. - - This is because an action runs synchronously and the user is waiting for the result. - """ - raise RuntimeError('cannot defer action events') - - def restore(self, snapshot: dict) -> None: - """Used by the operator framework to record the action. - - Not meant to be called directly by Charm code. - """ - env_action_name = os.environ.get('JUJU_ACTION_NAME') - event_action_name = self.handle.kind[:-len('_action')].replace('_', '-') - if event_action_name != env_action_name: - # This could only happen if the dev manually emits the action, or from a bug. - raise RuntimeError('action event kind does not match current action') - # Params are loaded at restore rather than __init__ because - # the model is not available in __init__. - self.params = self.framework.model._backend.action_get() - - def set_results(self, results: typing.Mapping) -> None: - """Report the result of the action. - - Args: - results: The result of the action as a Dict - """ - self.framework.model._backend.action_set(results) - - def log(self, message: str) -> None: - """Send a message that a user will see while the action is running. - - Args: - message: The message for the user. - """ - self.framework.model._backend.action_log(message) - - def fail(self, message: str = '') -> None: - """Report that this action has failed. - - Args: - message: Optional message to record why it has failed. - """ - self.framework.model._backend.action_fail(message) - - -class InstallEvent(HookEvent): - """Represents the `install` hook from Juju.""" - - -class StartEvent(HookEvent): - """Represents the `start` hook from Juju.""" - - -class StopEvent(HookEvent): - """Represents the `stop` hook from Juju.""" - - -class RemoveEvent(HookEvent): - """Represents the `remove` hook from Juju. """ - - -class ConfigChangedEvent(HookEvent): - """Represents the `config-changed` hook from Juju.""" - - -class UpdateStatusEvent(HookEvent): - """Represents the `update-status` hook from Juju.""" - - -class UpgradeCharmEvent(HookEvent): - """Represents the `upgrade-charm` hook from Juju. - - This will be triggered when a user has run `juju upgrade-charm`. It is run after Juju - has unpacked the upgraded charm code, and so this event will be handled with new code. - """ - - -class PreSeriesUpgradeEvent(HookEvent): - """Represents the `pre-series-upgrade` hook from Juju. - - This happens when a user has run `juju upgrade-series MACHINE prepare` and - will fire for each unit that is running on the machine, telling them that - the user is preparing to upgrade the Machine's series (eg trusty->bionic). - The charm should take actions to prepare for the upgrade (a database charm - would want to write out a version-independent dump of the database, so that - when a new version of the database is available in a new series, it can be - used.) - Once all units on a machine have run `pre-series-upgrade`, the user will - initiate the steps to actually upgrade the machine (eg `do-release-upgrade`). - When the upgrade has been completed, the :class:`PostSeriesUpgradeEvent` will fire. - """ - - -class PostSeriesUpgradeEvent(HookEvent): - """Represents the `post-series-upgrade` hook from Juju. - - This is run after the user has done a distribution upgrade (or rolled back - and kept the same series). It is called in response to - `juju upgrade-series MACHINE complete`. Charms are expected to do whatever - steps are necessary to reconfigure their applications for the new series. - """ - - -class LeaderElectedEvent(HookEvent): - """Represents the `leader-elected` hook from Juju. - - Juju will trigger this when a new lead unit is chosen for a given application. - This represents the leader of the charm information (not necessarily the primary - of a running application). The main utility is that charm authors can know - that only one unit will be a leader at any given time, so they can do - configuration, etc, that would otherwise require coordination between units. - (eg, selecting a password for a new relation) - """ - - -class LeaderSettingsChangedEvent(HookEvent): - """Represents the `leader-settings-changed` hook from Juju. - - Deprecated. This represents when a lead unit would call `leader-set` to inform - the other units of an application that they have new information to handle. - This has been deprecated in favor of using a Peer relation, and having the - leader set a value in the Application data bag for that peer relation. - (see :class:`RelationChangedEvent`). - """ - - -class CollectMetricsEvent(HookEvent): - """Represents the `collect-metrics` hook from Juju. - - Note that events firing during a CollectMetricsEvent are currently - sandboxed in how they can interact with Juju. To report metrics - use :meth:`.add_metrics`. - """ - - def add_metrics(self, metrics: typing.Mapping, labels: typing.Mapping = None) -> None: - """Record metrics that have been gathered by the charm for this unit. - - Args: - metrics: A collection of {key: float} pairs that contains the - metrics that have been gathered - labels: {key:value} strings that can be applied to the - metrics that are being gathered - """ - self.framework.model._backend.add_metrics(metrics, labels) - - -class RelationEvent(HookEvent): - """A base class representing the various relation lifecycle events. - - Charmers should not be creating RelationEvents directly. The events will be - generated by the framework from Juju related events. Users can observe them - from the various `CharmBase.on[relation_name].relation_*` events. - - Attributes: - relation: The Relation involved in this event - app: The remote application that has triggered this event - unit: The remote unit that has triggered this event. This may be None - if the relation event was triggered as an Application level event - """ - - def __init__(self, handle, relation, app=None, unit=None): - super().__init__(handle) - - if unit is not None and unit.app != app: - raise RuntimeError( - 'cannot create RelationEvent with application {} and unit {}'.format(app, unit)) - - self.relation = relation - self.app = app - self.unit = unit - - def snapshot(self) -> dict: - """Used by the framework to serialize the event to disk. - - Not meant to be called by Charm code. - """ - snapshot = { - 'relation_name': self.relation.name, - 'relation_id': self.relation.id, - } - if self.app: - snapshot['app_name'] = self.app.name - if self.unit: - snapshot['unit_name'] = self.unit.name - return snapshot - - def restore(self, snapshot: dict) -> None: - """Used by the framework to deserialize the event from disk. - - Not meant to be called by Charm code. - """ - self.relation = self.framework.model.get_relation( - snapshot['relation_name'], snapshot['relation_id']) - - app_name = snapshot.get('app_name') - if app_name: - self.app = self.framework.model.get_app(app_name) - else: - self.app = None - - unit_name = snapshot.get('unit_name') - if unit_name: - self.unit = self.framework.model.get_unit(unit_name) - else: - self.unit = None - - -class RelationCreatedEvent(RelationEvent): - """Represents the `relation-created` hook from Juju. - - This is triggered when a new relation to another app is added in Juju. This - can occur before units for those applications have started. All existing - relations should be established before start. - """ - - -class RelationJoinedEvent(RelationEvent): - """Represents the `relation-joined` hook from Juju. - - This is triggered whenever a new unit of a related application joins the relation. - (eg, a unit was added to an existing related app, or a new relation was established - with an application that already had units.) - """ - - -class RelationChangedEvent(RelationEvent): - """Represents the `relation-changed` hook from Juju. - - This is triggered whenever there is a change to the data bucket for a related - application or unit. Look at `event.relation.data[event.unit/app]` to see the - new information. - """ - - -class RelationDepartedEvent(RelationEvent): - """Represents the `relation-departed` hook from Juju. - - This is the inverse of the RelationJoinedEvent, representing when a unit - is leaving the relation (the unit is being removed, the app is being removed, - the relation is being removed). It is fired once for each unit that is - going away. - """ - - -class RelationBrokenEvent(RelationEvent): - """Represents the `relation-broken` hook from Juju. - - If a relation is being removed (`juju remove-relation` or `juju remove-application`), - once all the units have been removed, RelationBrokenEvent will fire to signal - that the relationship has been fully terminated. - """ - - -class StorageEvent(HookEvent): - """Base class representing Storage related events.""" - - -class StorageAttachedEvent(StorageEvent): - """Represents the `storage-attached` hook from Juju. - - Called when new storage is available for the charm to use. - """ - - -class StorageDetachingEvent(StorageEvent): - """Represents the `storage-detaching` hook from Juju. - - Called when storage a charm has been using is going away. - """ - - -class CharmEvents(ObjectEvents): - """The events that are generated by Juju in response to the lifecycle of an application.""" - - install = EventSource(InstallEvent) - start = EventSource(StartEvent) - stop = EventSource(StopEvent) - remove = EventSource(RemoveEvent) - update_status = EventSource(UpdateStatusEvent) - config_changed = EventSource(ConfigChangedEvent) - upgrade_charm = EventSource(UpgradeCharmEvent) - pre_series_upgrade = EventSource(PreSeriesUpgradeEvent) - post_series_upgrade = EventSource(PostSeriesUpgradeEvent) - leader_elected = EventSource(LeaderElectedEvent) - leader_settings_changed = EventSource(LeaderSettingsChangedEvent) - collect_metrics = EventSource(CollectMetricsEvent) - - -class CharmBase(Object): - """Base class that represents the Charm overall. - - Usually this initialization is done by ops.main.main() rather than Charm authors - directly instantiating a Charm. - - Args: - framework: The framework responsible for managing the Model and events for this - Charm. - key: Arbitrary key to distinguish this instance of CharmBase from another. - Generally is None when initialized by the framework. For charms instantiated by - main.main(), this is currenly None. - Attributes: - on: Defines all events that the Charm will fire. - """ - - on = CharmEvents() - - def __init__(self, framework: Framework, key: typing.Optional[str]): - """Initialize the Charm with its framework and application name. - - """ - super().__init__(framework, key) - - for relation_name in self.framework.meta.relations: - relation_name = relation_name.replace('-', '_') - self.on.define_event(relation_name + '_relation_created', RelationCreatedEvent) - self.on.define_event(relation_name + '_relation_joined', RelationJoinedEvent) - self.on.define_event(relation_name + '_relation_changed', RelationChangedEvent) - self.on.define_event(relation_name + '_relation_departed', RelationDepartedEvent) - self.on.define_event(relation_name + '_relation_broken', RelationBrokenEvent) - - for storage_name in self.framework.meta.storages: - storage_name = storage_name.replace('-', '_') - self.on.define_event(storage_name + '_storage_attached', StorageAttachedEvent) - self.on.define_event(storage_name + '_storage_detaching', StorageDetachingEvent) - - for action_name in self.framework.meta.actions: - action_name = action_name.replace('-', '_') - self.on.define_event(action_name + '_action', ActionEvent) - - @property - def app(self) -> model.Application: - """Application that this unit is part of.""" - return self.framework.model.app - - @property - def unit(self) -> model.Unit: - """Unit that this execution is responsible for.""" - return self.framework.model.unit - - @property - def meta(self) -> 'CharmMeta': - """CharmMeta of this charm. - """ - return self.framework.meta - - @property - def charm_dir(self) -> pathlib.Path: - """Root directory of the Charm as it is running. - """ - return self.framework.charm_dir - - -class CharmMeta: - """Object containing the metadata for the charm. - - This is read from metadata.yaml and/or actions.yaml. Generally charms will - define this information, rather than reading it at runtime. This class is - mostly for the framework to understand what the charm has defined. - - The maintainers, tags, terms, series, and extra_bindings attributes are all - lists of strings. The requires, provides, peers, relations, storage, - resources, and payloads attributes are all mappings of names to instances - of the respective RelationMeta, StorageMeta, ResourceMeta, or PayloadMeta. - - The relations attribute is a convenience accessor which includes all of the - requires, provides, and peers RelationMeta items. If needed, the role of - the relation definition can be obtained from its role attribute. - - Attributes: - name: The name of this charm - summary: Short description of what this charm does - description: Long description for this charm - maintainers: A list of strings of the email addresses of the maintainers - of this charm. - tags: Charm store tag metadata for categories associated with this charm. - terms: Charm store terms that should be agreed to before this charm can - be deployed. (Used for things like licensing issues.) - series: The list of supported OS series that this charm can support. - The first entry in the list is the default series that will be - used by deploy if no other series is requested by the user. - subordinate: True/False whether this charm is intended to be used as a - subordinate charm. - min_juju_version: If supplied, indicates this charm needs features that - are not available in older versions of Juju. - requires: A dict of {name: :class:`RelationMeta` } for each 'requires' relation. - provides: A dict of {name: :class:`RelationMeta` } for each 'provides' relation. - peers: A dict of {name: :class:`RelationMeta` } for each 'peer' relation. - relations: A dict containing all :class:`RelationMeta` attributes (merged from other - sections) - storages: A dict of {name: :class:`StorageMeta`} for each defined storage. - resources: A dict of {name: :class:`ResourceMeta`} for each defined resource. - payloads: A dict of {name: :class:`PayloadMeta`} for each defined payload. - extra_bindings: A dict of additional named bindings that a charm can use - for network configuration. - actions: A dict of {name: :class:`ActionMeta`} for actions that the charm has defined. - Args: - raw: a mapping containing the contents of metadata.yaml - actions_raw: a mapping containing the contents of actions.yaml - """ - - def __init__(self, raw: dict = {}, actions_raw: dict = {}): - self.name = raw.get('name', '') - self.summary = raw.get('summary', '') - self.description = raw.get('description', '') - self.maintainers = [] - if 'maintainer' in raw: - self.maintainers.append(raw['maintainer']) - if 'maintainers' in raw: - self.maintainers.extend(raw['maintainers']) - self.tags = raw.get('tags', []) - self.terms = raw.get('terms', []) - self.series = raw.get('series', []) - self.subordinate = raw.get('subordinate', False) - self.min_juju_version = raw.get('min-juju-version') - self.requires = {name: RelationMeta('requires', name, rel) - for name, rel in raw.get('requires', {}).items()} - self.provides = {name: RelationMeta('provides', name, rel) - for name, rel in raw.get('provides', {}).items()} - # TODO: (jam 2020-05-11) The *role* should be 'peer' even though it comes from the - # 'peers' section. - self.peers = {name: RelationMeta('peers', name, rel) - for name, rel in raw.get('peers', {}).items()} - self.relations = {} - self.relations.update(self.requires) - self.relations.update(self.provides) - self.relations.update(self.peers) - self.storages = {name: StorageMeta(name, storage) - for name, storage in raw.get('storage', {}).items()} - self.resources = {name: ResourceMeta(name, res) - for name, res in raw.get('resources', {}).items()} - self.payloads = {name: PayloadMeta(name, payload) - for name, payload in raw.get('payloads', {}).items()} - self.extra_bindings = raw.get('extra-bindings', {}) - self.actions = {name: ActionMeta(name, action) for name, action in actions_raw.items()} - - @classmethod - def from_yaml( - cls, metadata: typing.Union[str, typing.TextIO], - actions: typing.Optional[typing.Union[str, typing.TextIO]] = None): - """Instantiate a CharmMeta from a YAML description of metadata.yaml. - - Args: - metadata: A YAML description of charm metadata (name, relations, etc.) - This can be a simple string, or a file-like object. (passed to `yaml.safe_load`). - actions: YAML description of Actions for this charm (eg actions.yaml) - """ - meta = yaml.safe_load(metadata) - raw_actions = {} - if actions is not None: - raw_actions = yaml.safe_load(actions) - return cls(meta, raw_actions) - - -class RelationMeta: - """Object containing metadata about a relation definition. - - Should not be constructed directly by Charm code. Is gotten from one of - :attr:`CharmMeta.peers`, :attr:`CharmMeta.requires`, :attr:`CharmMeta.provides`, - :attr:`CharmMeta.relations`. - - Attributes: - role: This is one of requires/provides/peers - relation_name: Name of this relation from metadata.yaml - interface_name: Optional definition of the interface protocol. - scope: "global" or "container" scope based on how the relation should be used. - """ - - def __init__(self, role, relation_name, raw): - self.role = role - self.relation_name = relation_name - self.interface_name = raw['interface'] - self.scope = raw.get('scope') - - -class StorageMeta: - """Object containing metadata about a storage definition.""" - - def __init__(self, name, raw): - self.storage_name = name - self.type = raw['type'] - self.description = raw.get('description', '') - self.shared = raw.get('shared', False) - self.read_only = raw.get('read-only', False) - self.minimum_size = raw.get('minimum-size') - self.location = raw.get('location') - self.multiple_range = None - if 'multiple' in raw: - range = raw['multiple']['range'] - if '-' not in range: - self.multiple_range = (int(range), int(range)) - else: - range = range.split('-') - self.multiple_range = (int(range[0]), int(range[1]) if range[1] else None) - - -class ResourceMeta: - """Object containing metadata about a resource definition.""" - - def __init__(self, name, raw): - self.resource_name = name - self.type = raw['type'] - self.filename = raw.get('filename', None) - self.description = raw.get('description', '') - - -class PayloadMeta: - """Object containing metadata about a payload definition.""" - - def __init__(self, name, raw): - self.payload_name = name - self.type = raw['type'] - - -class ActionMeta: - """Object containing metadata about an action's definition.""" - - def __init__(self, name, raw=None): - raw = raw or {} - self.name = name - self.title = raw.get('title', '') - self.description = raw.get('description', '') - self.parameters = raw.get('params', {}) # {: } - self.required = raw.get('required', []) # [, ...] diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/framework.py b/magma/squid_cnf/charms/squid/mod/operator/ops/framework.py deleted file mode 100755 index 51d46ba1..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/framework.py +++ /dev/null @@ -1,1134 +0,0 @@ -# Copyright 2019-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. - -import collections -import collections.abc -import inspect -import keyword -import marshal -import os -import pdb -import pickle -import re -import sqlite3 -import sys -import types -import weakref -from datetime import timedelta - -from ops import charm - - -class Handle: - """Handle defines a name for an object in the form of a hierarchical path. - - The provided parent is the object (or that object's handle) that this handle - sits under, or None if the object identified by this handle stands by itself - as the root of its own hierarchy. - - The handle kind is a string that defines a namespace so objects with the - same parent and kind will have unique keys. - - The handle key is a string uniquely identifying the object. No other objects - under the same parent and kind may have the same key. - """ - - def __init__(self, parent, kind, key): - if parent and not isinstance(parent, Handle): - parent = parent.handle - self._parent = parent - self._kind = kind - self._key = key - if parent: - if key: - self._path = "{}/{}[{}]".format(parent, kind, key) - else: - self._path = "{}/{}".format(parent, kind) - else: - if key: - self._path = "{}[{}]".format(kind, key) - else: - self._path = "{}".format(kind) - - def nest(self, kind, key): - return Handle(self, kind, key) - - def __hash__(self): - return hash((self.parent, self.kind, self.key)) - - def __eq__(self, other): - return (self.parent, self.kind, self.key) == (other.parent, other.kind, other.key) - - def __str__(self): - return self.path - - @property - def parent(self): - return self._parent - - @property - def kind(self): - return self._kind - - @property - def key(self): - return self._key - - @property - def path(self): - return self._path - - @classmethod - def from_path(cls, path): - handle = None - for pair in path.split("/"): - pair = pair.split("[") - good = False - if len(pair) == 1: - kind, key = pair[0], None - good = True - elif len(pair) == 2: - kind, key = pair - if key and key[-1] == ']': - key = key[:-1] - good = True - if not good: - raise RuntimeError("attempted to restore invalid handle path {}".format(path)) - handle = Handle(handle, kind, key) - return handle - - -class EventBase: - - def __init__(self, handle): - self.handle = handle - self.deferred = False - - def defer(self): - self.deferred = True - - def snapshot(self): - """Return the snapshot data that should be persisted. - - Subclasses must override to save any custom state. - """ - return None - - def restore(self, snapshot): - """Restore the value state from the given snapshot. - - Subclasses must override to restore their custom state. - """ - self.deferred = False - - -class EventSource: - """EventSource wraps an event type with a descriptor to facilitate observing and emitting. - - It is generally used as: - - class SomethingHappened(EventBase): - pass - - class SomeObject(Object): - something_happened = EventSource(SomethingHappened) - - With that, instances of that type will offer the someobj.something_happened - attribute which is a BoundEvent and may be used to emit and observe the event. - """ - - def __init__(self, event_type): - if not isinstance(event_type, type) or not issubclass(event_type, EventBase): - raise RuntimeError( - 'Event requires a subclass of EventBase as an argument, got {}'.format(event_type)) - self.event_type = event_type - self.event_kind = None - self.emitter_type = None - - def _set_name(self, emitter_type, event_kind): - if self.event_kind is not None: - raise RuntimeError( - 'EventSource({}) reused as {}.{} and {}.{}'.format( - self.event_type.__name__, - self.emitter_type.__name__, - self.event_kind, - emitter_type.__name__, - event_kind, - )) - self.event_kind = event_kind - self.emitter_type = emitter_type - - def __get__(self, emitter, emitter_type=None): - if emitter is None: - return self - # Framework might not be available if accessed as CharmClass.on.event - # rather than charm_instance.on.event, but in that case it couldn't be - # emitted anyway, so there's no point to registering it. - framework = getattr(emitter, 'framework', None) - if framework is not None: - framework.register_type(self.event_type, emitter, self.event_kind) - return BoundEvent(emitter, self.event_type, self.event_kind) - - -class BoundEvent: - - def __repr__(self): - return ''.format( - self.event_type.__name__, - type(self.emitter).__name__, - self.event_kind, - hex(id(self)), - ) - - def __init__(self, emitter, event_type, event_kind): - self.emitter = emitter - self.event_type = event_type - self.event_kind = event_kind - - def emit(self, *args, **kwargs): - """Emit event to all registered observers. - - The current storage state is committed before and after each observer is notified. - """ - framework = self.emitter.framework - key = framework._next_event_key() - event = self.event_type(Handle(self.emitter, self.event_kind, key), *args, **kwargs) - framework._emit(event) - - -class HandleKind: - """Helper descriptor to define the Object.handle_kind field. - - The handle_kind for an object defaults to its type name, but it may - be explicitly overridden if desired. - """ - - def __get__(self, obj, obj_type): - kind = obj_type.__dict__.get("handle_kind") - if kind: - return kind - return obj_type.__name__ - - -class _Metaclass(type): - """Helper class to ensure proper instantiation of Object-derived classes. - - This class currently has a single purpose: events derived from EventSource - that are class attributes of Object-derived classes need to be told what - their name is in that class. For example, in - - class SomeObject(Object): - something_happened = EventSource(SomethingHappened) - - the instance of EventSource needs to know it's called 'something_happened'. - - Starting from python 3.6 we could use __set_name__ on EventSource for this, - but until then this (meta)class does the equivalent work. - - TODO: when we drop support for 3.5 drop this class, and rename _set_name in - EventSource to __set_name__; everything should continue to work. - - """ - - def __new__(typ, *a, **kw): - k = super().__new__(typ, *a, **kw) - # k is now the Object-derived class; loop over its class attributes - for n, v in vars(k).items(): - # we could do duck typing here if we want to support - # non-EventSource-derived shenanigans. We don't. - if isinstance(v, EventSource): - # this is what 3.6+ does automatically for us: - v._set_name(k, n) - return k - - -class Object(metaclass=_Metaclass): - - handle_kind = HandleKind() - - def __init__(self, parent, key): - kind = self.handle_kind - if isinstance(parent, Framework): - self.framework = parent - # Avoid Framework instances having a circular reference to themselves. - if self.framework is self: - self.framework = weakref.proxy(self.framework) - self.handle = Handle(None, kind, key) - else: - self.framework = parent.framework - self.handle = Handle(parent, kind, key) - self.framework._track(self) - - # TODO Detect conflicting handles here. - - @property - def model(self): - return self.framework.model - - -class ObjectEvents(Object): - """Convenience type to allow defining .on attributes at class level.""" - - handle_kind = "on" - - def __init__(self, parent=None, key=None): - if parent is not None: - super().__init__(parent, key) - else: - self._cache = weakref.WeakKeyDictionary() - - def __get__(self, emitter, emitter_type): - if emitter is None: - return self - instance = self._cache.get(emitter) - if instance is None: - # Same type, different instance, more data. Doing this unusual construct - # means people can subclass just this one class to have their own 'on'. - instance = self._cache[emitter] = type(self)(emitter) - return instance - - @classmethod - def define_event(cls, event_kind, event_type): - """Define an event on this type at runtime. - - cls: a type to define an event on. - - event_kind: an attribute name that will be used to access the - event. Must be a valid python identifier, not be a keyword - or an existing attribute. - - event_type: a type of the event to define. - - """ - prefix = 'unable to define an event with event_kind that ' - if not event_kind.isidentifier(): - raise RuntimeError(prefix + 'is not a valid python identifier: ' + event_kind) - elif keyword.iskeyword(event_kind): - raise RuntimeError(prefix + 'is a python keyword: ' + event_kind) - try: - getattr(cls, event_kind) - raise RuntimeError( - prefix + 'overlaps with an existing type {} attribute: {}'.format(cls, event_kind)) - except AttributeError: - pass - - event_descriptor = EventSource(event_type) - event_descriptor._set_name(cls, event_kind) - setattr(cls, event_kind, event_descriptor) - - def events(self): - """Return a mapping of event_kinds to bound_events for all available events. - """ - events_map = {} - # We have to iterate over the class rather than instance to allow for properties which - # might call this method (e.g., event views), leading to infinite recursion. - for attr_name, attr_value in inspect.getmembers(type(self)): - if isinstance(attr_value, EventSource): - # We actually care about the bound_event, however, since it - # provides the most info for users of this method. - event_kind = attr_name - bound_event = getattr(self, event_kind) - events_map[event_kind] = bound_event - return events_map - - def __getitem__(self, key): - return PrefixedEvents(self, key) - - -class PrefixedEvents: - - def __init__(self, emitter, key): - self._emitter = emitter - self._prefix = key.replace("-", "_") + '_' - - def __getattr__(self, name): - return getattr(self._emitter, self._prefix + name) - - -class PreCommitEvent(EventBase): - pass - - -class CommitEvent(EventBase): - pass - - -class FrameworkEvents(ObjectEvents): - pre_commit = EventSource(PreCommitEvent) - commit = EventSource(CommitEvent) - - -class NoSnapshotError(Exception): - - def __init__(self, handle_path): - self.handle_path = handle_path - - def __str__(self): - return 'no snapshot data found for {} object'.format(self.handle_path) - - -class NoTypeError(Exception): - - def __init__(self, handle_path): - self.handle_path = handle_path - - def __str__(self): - return "cannot restore {} since no class was registered for it".format(self.handle_path) - - -class SQLiteStorage: - - DB_LOCK_TIMEOUT = timedelta(hours=1) - - def __init__(self, filename): - # The isolation_level argument is set to None such that the implicit - # transaction management behavior of the sqlite3 module is disabled. - self._db = sqlite3.connect(str(filename), - isolation_level=None, - timeout=self.DB_LOCK_TIMEOUT.total_seconds()) - self._setup() - - def _setup(self): - # Make sure that the database is locked until the connection is closed, - # not until the transaction ends. - self._db.execute("PRAGMA locking_mode=EXCLUSIVE") - c = self._db.execute("BEGIN") - c.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='snapshot'") - if c.fetchone()[0] == 0: - # Keep in mind what might happen if the process dies somewhere below. - # The system must not be rendered permanently broken by that. - self._db.execute("CREATE TABLE snapshot (handle TEXT PRIMARY KEY, data BLOB)") - self._db.execute(''' - CREATE TABLE notice ( - sequence INTEGER PRIMARY KEY AUTOINCREMENT, - event_path TEXT, - observer_path TEXT, - method_name TEXT) - ''') - self._db.commit() - - def close(self): - self._db.close() - - def commit(self): - self._db.commit() - - # There's commit but no rollback. For abort to be supported, we'll need logic that - # can rollback decisions made by third-party code in terms of the internal state - # of objects that have been snapshotted, and hooks to let them know about it and - # take the needed actions to undo their logic until the last snapshot. - # This is doable but will increase significantly the chances for mistakes. - - def save_snapshot(self, handle_path, snapshot_data): - self._db.execute("REPLACE INTO snapshot VALUES (?, ?)", (handle_path, snapshot_data)) - - def load_snapshot(self, handle_path): - c = self._db.cursor() - c.execute("SELECT data FROM snapshot WHERE handle=?", (handle_path,)) - row = c.fetchone() - if row: - return row[0] - return None - - def drop_snapshot(self, handle_path): - self._db.execute("DELETE FROM snapshot WHERE handle=?", (handle_path,)) - - def save_notice(self, event_path, observer_path, method_name): - self._db.execute('INSERT INTO notice VALUES (NULL, ?, ?, ?)', - (event_path, observer_path, method_name)) - - def drop_notice(self, event_path, observer_path, method_name): - self._db.execute(''' - DELETE FROM notice - WHERE event_path=? - AND observer_path=? - AND method_name=? - ''', (event_path, observer_path, method_name)) - - def notices(self, event_path): - if event_path: - c = self._db.execute(''' - SELECT event_path, observer_path, method_name - FROM notice - WHERE event_path=? - ORDER BY sequence - ''', (event_path,)) - else: - c = self._db.execute(''' - SELECT event_path, observer_path, method_name - FROM notice - ORDER BY sequence - ''') - while True: - rows = c.fetchmany() - if not rows: - break - for row in rows: - yield tuple(row) - - -# the message to show to the user when a pdb breakpoint goes active -_BREAKPOINT_WELCOME_MESSAGE = """ -Starting pdb to debug charm operator. -Run `h` for help, `c` to continue, or `exit`/CTRL-d to abort. -Future breakpoints may interrupt execution again. -More details at https://discourse.jujucharms.com/t/debugging-charm-hooks - -""" - - -class Framework(Object): - - on = FrameworkEvents() - - # Override properties from Object so that we can set them in __init__. - model = None - meta = None - charm_dir = None - - def __init__(self, data_path, charm_dir, meta, model): - - super().__init__(self, None) - - self._data_path = data_path - self.charm_dir = charm_dir - self.meta = meta - self.model = model - self._observers = [] # [(observer_path, method_name, parent_path, event_key)] - self._observer = weakref.WeakValueDictionary() # {observer_path: observer} - self._objects = weakref.WeakValueDictionary() - self._type_registry = {} # {(parent_path, kind): cls} - self._type_known = set() # {cls} - - self._storage = SQLiteStorage(data_path) - - # We can't use the higher-level StoredState because it relies on events. - self.register_type(StoredStateData, None, StoredStateData.handle_kind) - stored_handle = Handle(None, StoredStateData.handle_kind, '_stored') - try: - self._stored = self.load_snapshot(stored_handle) - except NoSnapshotError: - self._stored = StoredStateData(self, '_stored') - self._stored['event_count'] = 0 - - # Hook into builtin breakpoint, so if Python >= 3.7, devs will be able to just do - # breakpoint(); if Python < 3.7, this doesn't affect anything - sys.breakpointhook = self.breakpoint - - # Flag to indicate that we already presented the welcome message in a debugger breakpoint - self._breakpoint_welcomed = False - - # Parse once the env var, which may be used multiple times later - debug_at = os.environ.get('JUJU_DEBUG_AT') - self._juju_debug_at = debug_at.split(',') if debug_at else () - - def close(self): - self._storage.close() - - def _track(self, obj): - """Track object and ensure it is the only object created using its handle path.""" - if obj is self: - # Framework objects don't track themselves - return - if obj.handle.path in self.framework._objects: - raise RuntimeError( - 'two objects claiming to be {} have been created'.format(obj.handle.path)) - self._objects[obj.handle.path] = obj - - def _forget(self, obj): - """Stop tracking the given object. See also _track.""" - self._objects.pop(obj.handle.path, None) - - def commit(self): - # Give a chance for objects to persist data they want to before a commit is made. - self.on.pre_commit.emit() - # Make sure snapshots are saved by instances of StoredStateData. Any possible state - # modifications in on_commit handlers of instances of other classes will not be persisted. - self.on.commit.emit() - # Save our event count after all events have been emitted. - self.save_snapshot(self._stored) - self._storage.commit() - - def register_type(self, cls, parent, kind=None): - if parent and not isinstance(parent, Handle): - parent = parent.handle - if parent: - parent_path = parent.path - else: - parent_path = None - if not kind: - kind = cls.handle_kind - self._type_registry[(parent_path, kind)] = cls - self._type_known.add(cls) - - def save_snapshot(self, value): - """Save a persistent snapshot of the provided value. - - The provided value must implement the following interface: - - value.handle = Handle(...) - value.snapshot() => {...} # Simple builtin types only. - value.restore(snapshot) # Restore custom state from prior snapshot. - """ - if type(value) not in self._type_known: - raise RuntimeError( - 'cannot save {} values before registering that type'.format(type(value).__name__)) - data = value.snapshot() - - # Use marshal as a validator, enforcing the use of simple types, as we later the - # information is really pickled, which is too error prone for future evolution of the - # stored data (e.g. if the developer stores a custom object and later changes its - # class name; when unpickling the original class will not be there and event - # data loading will fail). - try: - marshal.dumps(data) - except ValueError: - msg = "unable to save the data for {}, it must contain only simple types: {!r}" - raise ValueError(msg.format(value.__class__.__name__, data)) - - # Use pickle for serialization, so the value remains portable. - raw_data = pickle.dumps(data) - self._storage.save_snapshot(value.handle.path, raw_data) - - def load_snapshot(self, handle): - parent_path = None - if handle.parent: - parent_path = handle.parent.path - cls = self._type_registry.get((parent_path, handle.kind)) - if not cls: - raise NoTypeError(handle.path) - raw_data = self._storage.load_snapshot(handle.path) - if not raw_data: - raise NoSnapshotError(handle.path) - data = pickle.loads(raw_data) - obj = cls.__new__(cls) - obj.framework = self - obj.handle = handle - obj.restore(data) - self._track(obj) - return obj - - def drop_snapshot(self, handle): - self._storage.drop_snapshot(handle.path) - - def observe(self, bound_event, observer): - """Register observer to be called when bound_event is emitted. - - The bound_event is generally provided as an attribute of the object that emits - the event, and is created in this style: - - class SomeObject: - something_happened = Event(SomethingHappened) - - That event may be observed as: - - framework.observe(someobj.something_happened, self.on_something_happened) - - If the method to be called follows the name convention "on_", it - may be omitted from the observe call. That means the above is equivalent to: - - framework.observe(someobj.something_happened, self) - - """ - if not isinstance(bound_event, BoundEvent): - raise RuntimeError( - 'Framework.observe requires a BoundEvent as second parameter, got {}'.format( - bound_event)) - - event_type = bound_event.event_type - event_kind = bound_event.event_kind - emitter = bound_event.emitter - - self.register_type(event_type, emitter, event_kind) - - if hasattr(emitter, "handle"): - emitter_path = emitter.handle.path - else: - raise RuntimeError( - 'event emitter {} must have a "handle" attribute'.format(type(emitter).__name__)) - - method_name = None - if isinstance(observer, types.MethodType): - method_name = observer.__name__ - observer = observer.__self__ - else: - method_name = "on_" + event_kind - if not hasattr(observer, method_name): - raise RuntimeError( - 'Observer method not provided explicitly' - ' and {} type has no "{}" method'.format(type(observer).__name__, - method_name)) - - # Validate that the method has an acceptable call signature. - sig = inspect.signature(getattr(observer, method_name)) - # Self isn't included in the params list, so the first arg will be the event. - extra_params = list(sig.parameters.values())[1:] - if not sig.parameters: - raise TypeError( - '{}.{} must accept event parameter'.format(type(observer).__name__, method_name)) - elif any(param.default is inspect.Parameter.empty for param in extra_params): - # Allow for additional optional params, since there's no reason to exclude them, but - # required params will break. - raise TypeError( - '{}.{} has extra required parameter'.format(type(observer).__name__, method_name)) - - # TODO Prevent the exact same parameters from being registered more than once. - - self._observer[observer.handle.path] = observer - self._observers.append((observer.handle.path, method_name, emitter_path, event_kind)) - - def _next_event_key(self): - """Return the next event key that should be used, incrementing the internal counter.""" - # Increment the count first; this means the keys will start at 1, and 0 - # means no events have been emitted. - self._stored['event_count'] += 1 - return str(self._stored['event_count']) - - def _emit(self, event): - """See BoundEvent.emit for the public way to call this.""" - - # Save the event for all known observers before the first notification - # takes place, so that either everyone interested sees it, or nobody does. - self.save_snapshot(event) - event_path = event.handle.path - event_kind = event.handle.kind - parent_path = event.handle.parent.path - # TODO Track observers by (parent_path, event_kind) rather than as a list of - # all observers. Avoiding linear search through all observers for every event - for observer_path, method_name, _parent_path, _event_kind in self._observers: - if _parent_path != parent_path: - continue - if _event_kind and _event_kind != event_kind: - continue - # Again, only commit this after all notices are saved. - self._storage.save_notice(event_path, observer_path, method_name) - self._reemit(event_path) - - def reemit(self): - """Reemit previously deferred events to the observers that deferred them. - - Only the specific observers that have previously deferred the event will be - notified again. Observers that asked to be notified about events after it's - been first emitted won't be notified, as that would mean potentially observing - events out of order. - """ - self._reemit() - - def _reemit(self, single_event_path=None): - last_event_path = None - deferred = True - for event_path, observer_path, method_name in self._storage.notices(single_event_path): - event_handle = Handle.from_path(event_path) - - if last_event_path != event_path: - if not deferred: - self._storage.drop_snapshot(last_event_path) - last_event_path = event_path - deferred = False - - try: - event = self.load_snapshot(event_handle) - except NoTypeError: - self._storage.drop_notice(event_path, observer_path, method_name) - continue - - event.deferred = False - observer = self._observer.get(observer_path) - if observer: - custom_handler = getattr(observer, method_name, None) - if custom_handler: - event_is_from_juju = isinstance(event, charm.HookEvent) - event_is_action = isinstance(event, charm.ActionEvent) - if (event_is_from_juju or event_is_action) and 'hook' in self._juju_debug_at: - # Present the welcome message and run under PDB. - self._show_debug_code_message() - pdb.runcall(custom_handler, event) - else: - # Regular call to the registered method. - custom_handler(event) - - if event.deferred: - deferred = True - else: - self._storage.drop_notice(event_path, observer_path, method_name) - # We intentionally consider this event to be dead and reload it from - # scratch in the next path. - self.framework._forget(event) - - if not deferred: - self._storage.drop_snapshot(last_event_path) - - def _show_debug_code_message(self): - """Present the welcome message (only once!) when using debugger functionality.""" - if not self._breakpoint_welcomed: - self._breakpoint_welcomed = True - print(_BREAKPOINT_WELCOME_MESSAGE, file=sys.stderr, end='') - - def breakpoint(self, name=None): - """Add breakpoint, optionally named, at the place where this method is called. - - For the breakpoint to be activated the JUJU_DEBUG_AT environment variable - must be set to "all" or to the specific name parameter provided, if any. In every - other situation calling this method does nothing. - - The framework also provides a standard breakpoint named "hook", that will - stop execution when a hook event is about to be handled. - - For those reasons, the "all" and "hook" breakpoint names are reserved. - """ - # If given, validate the name comply with all the rules - if name is not None: - if not isinstance(name, str): - raise TypeError('breakpoint names must be strings') - if name in ('hook', 'all'): - raise ValueError('breakpoint names "all" and "hook" are reserved') - if not re.match(r'^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$', name): - raise ValueError('breakpoint names must look like "foo" or "foo-bar"') - - indicated_breakpoints = self._juju_debug_at - if 'all' in indicated_breakpoints or name in indicated_breakpoints: - self._show_debug_code_message() - - # If we call set_trace() directly it will open the debugger *here*, so indicating - # it to use our caller's frame - code_frame = inspect.currentframe().f_back - pdb.Pdb().set_trace(code_frame) - - -class StoredStateData(Object): - - def __init__(self, parent, attr_name): - super().__init__(parent, attr_name) - self._cache = {} - self.dirty = False - - def __getitem__(self, key): - return self._cache.get(key) - - def __setitem__(self, key, value): - self._cache[key] = value - self.dirty = True - - def __contains__(self, key): - return key in self._cache - - def snapshot(self): - return self._cache - - def restore(self, snapshot): - self._cache = snapshot - self.dirty = False - - def on_commit(self, event): - if self.dirty: - self.framework.save_snapshot(self) - self.dirty = False - - -class BoundStoredState: - - def __init__(self, parent, attr_name): - parent.framework.register_type(StoredStateData, parent) - - handle = Handle(parent, StoredStateData.handle_kind, attr_name) - try: - data = parent.framework.load_snapshot(handle) - except NoSnapshotError: - data = StoredStateData(parent, attr_name) - - # __dict__ is used to avoid infinite recursion. - self.__dict__["_data"] = data - self.__dict__["_attr_name"] = attr_name - - parent.framework.observe(parent.framework.on.commit, self._data) - - def __getattr__(self, key): - # "on" is the only reserved key that can't be used in the data map. - if key == "on": - return self._data.on - if key not in self._data: - raise AttributeError("attribute '{}' is not stored".format(key)) - return _wrap_stored(self._data, self._data[key]) - - def __setattr__(self, key, value): - if key == "on": - raise AttributeError("attribute 'on' is reserved and cannot be set") - - value = _unwrap_stored(self._data, value) - - if not isinstance(value, (type(None), int, float, str, bytes, list, dict, set)): - raise AttributeError( - 'attribute {!r} cannot be a {}: must be int/float/dict/list/etc'.format( - key, type(value).__name__)) - - self._data[key] = _unwrap_stored(self._data, value) - - def set_default(self, **kwargs): - """"Set the value of any given key if it has not already been set""" - for k, v in kwargs.items(): - if k not in self._data: - self._data[k] = v - - -class StoredState: - """A class used to store data the charm needs persisted across invocations. - - Example:: - - class MyClass(Object): - _stored = StoredState() - - Instances of `MyClass` can transparently save state between invocations by - setting attributes on `_stored`. Initial state should be set with - `set_default` on the bound object, that is:: - - class MyClass(Object): - _stored = StoredState() - - def __init__(self, parent, key): - super().__init__(parent, key) - self._stored.set_default(seen=set()) - self.framework.observe(self.on.seen, self._on_seen) - - def _on_seen(self, event): - self._stored.seen.add(event.uuid) - - """ - - def __init__(self): - self.parent_type = None - self.attr_name = None - - def __get__(self, parent, parent_type=None): - if self.parent_type is not None and self.parent_type not in parent_type.mro(): - # the StoredState instance is being shared between two unrelated classes - # -> unclear what is exepcted of us -> bail out - raise RuntimeError( - 'StoredState shared by {} and {}'.format( - self.parent_type.__name__, parent_type.__name__)) - - if parent is None: - # accessing via the class directly (e.g. MyClass.stored) - return self - - bound = None - if self.attr_name is not None: - bound = parent.__dict__.get(self.attr_name) - if bound is not None: - # we already have the thing from a previous pass, huzzah - return bound - - # need to find ourselves amongst the parent's bases - for cls in parent_type.mro(): - for attr_name, attr_value in cls.__dict__.items(): - if attr_value is not self: - continue - # we've found ourselves! is it the first time? - if bound is not None: - # the StoredState instance is being stored in two different - # attributes -> unclear what is expected of us -> bail out - raise RuntimeError("StoredState shared by {0}.{1} and {0}.{2}".format( - cls.__name__, self.attr_name, attr_name)) - # we've found ourselves for the first time; save where, and bind the object - self.attr_name = attr_name - self.parent_type = cls - bound = BoundStoredState(parent, attr_name) - - if bound is not None: - # cache the bound object to avoid the expensive lookup the next time - # (don't use setattr, to keep things symmetric with the fast-path lookup above) - parent.__dict__[self.attr_name] = bound - return bound - - raise AttributeError( - 'cannot find {} attribute in type {}'.format( - self.__class__.__name__, parent_type.__name__)) - - -def _wrap_stored(parent_data, value): - t = type(value) - if t is dict: - return StoredDict(parent_data, value) - if t is list: - return StoredList(parent_data, value) - if t is set: - return StoredSet(parent_data, value) - return value - - -def _unwrap_stored(parent_data, value): - t = type(value) - if t is StoredDict or t is StoredList or t is StoredSet: - return value._under - return value - - -class StoredDict(collections.abc.MutableMapping): - - def __init__(self, stored_data, under): - self._stored_data = stored_data - self._under = under - - def __getitem__(self, key): - return _wrap_stored(self._stored_data, self._under[key]) - - def __setitem__(self, key, value): - self._under[key] = _unwrap_stored(self._stored_data, value) - self._stored_data.dirty = True - - def __delitem__(self, key): - del self._under[key] - self._stored_data.dirty = True - - def __iter__(self): - return self._under.__iter__() - - def __len__(self): - return len(self._under) - - def __eq__(self, other): - if isinstance(other, StoredDict): - return self._under == other._under - elif isinstance(other, collections.abc.Mapping): - return self._under == other - else: - return NotImplemented - - -class StoredList(collections.abc.MutableSequence): - - def __init__(self, stored_data, under): - self._stored_data = stored_data - self._under = under - - def __getitem__(self, index): - return _wrap_stored(self._stored_data, self._under[index]) - - def __setitem__(self, index, value): - self._under[index] = _unwrap_stored(self._stored_data, value) - self._stored_data.dirty = True - - def __delitem__(self, index): - del self._under[index] - self._stored_data.dirty = True - - def __len__(self): - return len(self._under) - - def insert(self, index, value): - self._under.insert(index, value) - self._stored_data.dirty = True - - def append(self, value): - self._under.append(value) - self._stored_data.dirty = True - - def __eq__(self, other): - if isinstance(other, StoredList): - return self._under == other._under - elif isinstance(other, collections.abc.Sequence): - return self._under == other - else: - return NotImplemented - - def __lt__(self, other): - if isinstance(other, StoredList): - return self._under < other._under - elif isinstance(other, collections.abc.Sequence): - return self._under < other - else: - return NotImplemented - - def __le__(self, other): - if isinstance(other, StoredList): - return self._under <= other._under - elif isinstance(other, collections.abc.Sequence): - return self._under <= other - else: - return NotImplemented - - def __gt__(self, other): - if isinstance(other, StoredList): - return self._under > other._under - elif isinstance(other, collections.abc.Sequence): - return self._under > other - else: - return NotImplemented - - def __ge__(self, other): - if isinstance(other, StoredList): - return self._under >= other._under - elif isinstance(other, collections.abc.Sequence): - return self._under >= other - else: - return NotImplemented - - -class StoredSet(collections.abc.MutableSet): - - def __init__(self, stored_data, under): - self._stored_data = stored_data - self._under = under - - def add(self, key): - self._under.add(key) - self._stored_data.dirty = True - - def discard(self, key): - self._under.discard(key) - self._stored_data.dirty = True - - def __contains__(self, key): - return key in self._under - - def __iter__(self): - return self._under.__iter__() - - def __len__(self): - return len(self._under) - - @classmethod - def _from_iterable(cls, it): - """Construct an instance of the class from any iterable input. - - Per https://docs.python.org/3/library/collections.abc.html - if the Set mixin is being used in a class with a different constructor signature, - you will need to override _from_iterable() with a classmethod that can construct - new instances from an iterable argument. - """ - return set(it) - - def __le__(self, other): - if isinstance(other, StoredSet): - return self._under <= other._under - elif isinstance(other, collections.abc.Set): - return self._under <= other - else: - return NotImplemented - - def __ge__(self, other): - if isinstance(other, StoredSet): - return self._under >= other._under - elif isinstance(other, collections.abc.Set): - return self._under >= other - else: - return NotImplemented - - def __eq__(self, other): - if isinstance(other, StoredSet): - return self._under == other._under - elif isinstance(other, collections.abc.Set): - return self._under == other - else: - return NotImplemented diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py b/magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py deleted file mode 100755 index 45178862..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py +++ /dev/null @@ -1,85 +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. - -import re -from functools import total_ordering - - -@total_ordering -class JujuVersion: - - PATTERN = r'''^ - (?P\d{1,9})\.(?P\d{1,9}) # and numbers are always there - ((?:\.|-(?P[a-z]+))(?P\d{1,9}))? # sometimes with . or - - (\.(?P\d{1,9}))?$ # and sometimes with a number. - ''' - - def __init__(self, version): - m = re.match(self.PATTERN, version, re.VERBOSE) - if not m: - raise RuntimeError('"{}" is not a valid Juju version string'.format(version)) - - d = m.groupdict() - self.major = int(m.group('major')) - self.minor = int(m.group('minor')) - self.tag = d['tag'] or '' - self.patch = int(d['patch'] or 0) - self.build = int(d['build'] or 0) - - def __repr__(self): - if self.tag: - s = '{}.{}-{}{}'.format(self.major, self.minor, self.tag, self.patch) - else: - s = '{}.{}.{}'.format(self.major, self.minor, self.patch) - if self.build > 0: - s += '.{}'.format(self.build) - return s - - def __eq__(self, other): - if self is other: - return True - if isinstance(other, str): - other = type(self)(other) - elif not isinstance(other, JujuVersion): - raise RuntimeError('cannot compare Juju version "{}" with "{}"'.format(self, other)) - return ( - self.major == other.major - and self.minor == other.minor - and self.tag == other.tag - and self.build == other.build - and self.patch == other.patch) - - def __lt__(self, other): - if self is other: - return False - if isinstance(other, str): - other = type(self)(other) - elif not isinstance(other, JujuVersion): - raise RuntimeError('cannot compare Juju version "{}" with "{}"'.format(self, other)) - - if self.major != other.major: - return self.major < other.major - elif self.minor != other.minor: - return self.minor < other.minor - elif self.tag != other.tag: - if not self.tag: - return False - elif not other.tag: - return True - return self.tag < other.tag - elif self.patch != other.patch: - return self.patch < other.patch - elif self.build != other.build: - return self.build < other.build - return False diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/log.py b/magma/squid_cnf/charms/squid/mod/operator/ops/log.py deleted file mode 100644 index a3f76a37..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/log.py +++ /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. - -import logging - - -class JujuLogHandler(logging.Handler): - """A handler for sending logs to Juju via juju-log.""" - - def __init__(self, model_backend, level=logging.DEBUG): - super().__init__(level) - self.model_backend = model_backend - - def emit(self, record): - self.model_backend.juju_log(record.levelname, self.format(record)) - - -def setup_root_logging(model_backend, debug=False): - """Setup python logging to forward messages to juju-log. - - By default, logging is set to DEBUG level, and messages will be filtered by Juju. - Charmers can also set their own default log level with:: - - logging.getLogger().setLevel(logging.INFO) - - model_backend -- a ModelBackend to use for juju-log - debug -- if True, write logs to stderr as well as to juju-log. - """ - logger = logging.getLogger() - logger.setLevel(logging.DEBUG) - logger.addHandler(JujuLogHandler(model_backend)) - if debug: - handler = logging.StreamHandler() - formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') - handler.setFormatter(formatter) - logger.addHandler(handler) diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/main.py b/magma/squid_cnf/charms/squid/mod/operator/ops/main.py deleted file mode 100755 index 0f5391d7..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/main.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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. - -import os -import subprocess -import sys -from pathlib import Path - -import yaml - -import ops.charm -import ops.framework -import ops.model -import logging - -from ops.log import setup_root_logging - -CHARM_STATE_FILE = '.unit-state.db' - - -logger = logging.getLogger() - - -def _get_charm_dir(): - charm_dir = os.environ.get("JUJU_CHARM_DIR") - if charm_dir is None: - # Assume $JUJU_CHARM_DIR/lib/op/main.py structure. - charm_dir = Path('{}/../../..'.format(__file__)).resolve() - else: - charm_dir = Path(charm_dir).resolve() - return charm_dir - - -def _load_metadata(charm_dir): - metadata = yaml.safe_load((charm_dir / 'metadata.yaml').read_text()) - - actions_meta = charm_dir / 'actions.yaml' - if actions_meta.exists(): - actions_metadata = yaml.safe_load(actions_meta.read_text()) - else: - actions_metadata = {} - return metadata, actions_metadata - - -def _create_event_link(charm, bound_event): - """Create a symlink for a particular event. - - charm -- A charm object. - bound_event -- An event for which to create a symlink. - """ - if issubclass(bound_event.event_type, ops.charm.HookEvent): - event_dir = charm.framework.charm_dir / 'hooks' - event_path = event_dir / bound_event.event_kind.replace('_', '-') - elif issubclass(bound_event.event_type, ops.charm.ActionEvent): - if not bound_event.event_kind.endswith("_action"): - raise RuntimeError( - 'action event name {} needs _action suffix'.format(bound_event.event_kind)) - event_dir = charm.framework.charm_dir / 'actions' - # The event_kind is suffixed with "_action" while the executable is not. - event_path = event_dir / bound_event.event_kind[:-len('_action')].replace('_', '-') - else: - raise RuntimeError( - 'cannot create a symlink: unsupported event type {}'.format(bound_event.event_type)) - - event_dir.mkdir(exist_ok=True) - if not event_path.exists(): - # CPython has different implementations for populating sys.argv[0] for Linux and Windows. - # For Windows it is always an absolute path (any symlinks are resolved) - # while for Linux it can be a relative path. - target_path = os.path.relpath(os.path.realpath(sys.argv[0]), str(event_dir)) - - # Ignore the non-symlink files or directories - # assuming the charm author knows what they are doing. - logger.debug( - 'Creating a new relative symlink at %s pointing to %s', - event_path, target_path) - event_path.symlink_to(target_path) - - -def _setup_event_links(charm_dir, charm): - """Set up links for supported events that originate from Juju. - - Whether a charm can handle an event or not can be determined by - introspecting which events are defined on it. - - Hooks or actions are created as symlinks to the charm code file - which is determined by inspecting symlinks provided by the charm - author at hooks/install or hooks/start. - - charm_dir -- A root directory of the charm. - charm -- An instance of the Charm class. - - """ - for bound_event in charm.on.events().values(): - # Only events that originate from Juju need symlinks. - if issubclass(bound_event.event_type, (ops.charm.HookEvent, ops.charm.ActionEvent)): - _create_event_link(charm, bound_event) - - -def _emit_charm_event(charm, event_name): - """Emits a charm event based on a Juju event name. - - charm -- A charm instance to emit an event from. - event_name -- A Juju event name to emit on a charm. - """ - event_to_emit = None - try: - event_to_emit = getattr(charm.on, event_name) - except AttributeError: - logger.debug("event %s not defined for %s", event_name, charm) - - # If the event is not supported by the charm implementation, do - # not error out or try to emit it. This is to support rollbacks. - if event_to_emit is not None: - args, kwargs = _get_event_args(charm, event_to_emit) - logger.debug('Emitting Juju event %s', event_name) - event_to_emit.emit(*args, **kwargs) - - -def _get_event_args(charm, bound_event): - event_type = bound_event.event_type - model = charm.framework.model - - if issubclass(event_type, ops.charm.RelationEvent): - relation_name = os.environ['JUJU_RELATION'] - relation_id = int(os.environ['JUJU_RELATION_ID'].split(':')[-1]) - relation = model.get_relation(relation_name, relation_id) - else: - relation = None - - remote_app_name = os.environ.get('JUJU_REMOTE_APP', '') - remote_unit_name = os.environ.get('JUJU_REMOTE_UNIT', '') - if remote_app_name or remote_unit_name: - if not remote_app_name: - if '/' not in remote_unit_name: - raise RuntimeError('invalid remote unit name: {}'.format(remote_unit_name)) - remote_app_name = remote_unit_name.split('/')[0] - args = [relation, model.get_app(remote_app_name)] - if remote_unit_name: - args.append(model.get_unit(remote_unit_name)) - return args, {} - elif relation: - return [relation], {} - return [], {} - - -def main(charm_class): - """Setup the charm and dispatch the observed event. - - The event name is based on the way this executable was called (argv[0]). - """ - charm_dir = _get_charm_dir() - - model_backend = ops.model.ModelBackend() - debug = ('JUJU_DEBUG' in os.environ) - setup_root_logging(model_backend, debug=debug) - - # Process the Juju event relevant to the current hook execution - # JUJU_HOOK_NAME, JUJU_FUNCTION_NAME, and JUJU_ACTION_NAME are not used - # in order to support simulation of events from debugging sessions. - # - # TODO: For Windows, when symlinks are used, this is not a valid - # method of getting an event name (see LP: #1854505). - juju_exec_path = Path(sys.argv[0]) - has_dispatch = juju_exec_path.name == 'dispatch' - if has_dispatch: - # The executable was 'dispatch', which means the actual hook we want to - # run needs to be looked up in the JUJU_DISPATCH_PATH env var, where it - # should be a path relative to the charm directory (the directory that - # holds `dispatch`). If that path actually exists, we want to run that - # before continuing. - dispatch_path = juju_exec_path.parent / Path(os.environ['JUJU_DISPATCH_PATH']) - if dispatch_path.exists() and dispatch_path.resolve() != juju_exec_path.resolve(): - argv = sys.argv.copy() - argv[0] = str(dispatch_path) - try: - subprocess.run(argv, check=True) - except subprocess.CalledProcessError as e: - logger.warning("hook %s exited with status %d", dispatch_path, e.returncode) - sys.exit(e.returncode) - juju_exec_path = dispatch_path - juju_event_name = juju_exec_path.name.replace('-', '_') - if juju_exec_path.parent.name == 'actions': - juju_event_name = '{}_action'.format(juju_event_name) - - metadata, actions_metadata = _load_metadata(charm_dir) - meta = ops.charm.CharmMeta(metadata, actions_metadata) - unit_name = os.environ['JUJU_UNIT_NAME'] - model = ops.model.Model(unit_name, meta, model_backend) - - # TODO: If Juju unit agent crashes after exit(0) from the charm code - # the framework will commit the snapshot but Juju will not commit its - # operation. - charm_state_path = charm_dir / CHARM_STATE_FILE - framework = ops.framework.Framework(charm_state_path, charm_dir, meta, model) - try: - charm = charm_class(framework, None) - - if not has_dispatch: - # When a charm is force-upgraded and a unit is in an error state Juju - # does not run upgrade-charm and instead runs the failed hook followed - # by config-changed. Given the nature of force-upgrading the hook setup - # code is not triggered on config-changed. - # - # 'start' event is included as Juju does not fire the install event for - # K8s charms (see LP: #1854635). - if (juju_event_name in ('install', 'start', 'upgrade_charm') - or juju_event_name.endswith('_storage_attached')): - _setup_event_links(charm_dir, charm) - - # TODO: Remove the collect_metrics check below as soon as the relevant - # Juju changes are made. - # - # Skip reemission of deferred events for collect-metrics events because - # they do not have the full access to all hook tools. - if juju_event_name != 'collect_metrics': - framework.reemit() - - _emit_charm_event(charm, juju_event_name) - - framework.commit() - finally: - framework.close() diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/model.py b/magma/squid_cnf/charms/squid/mod/operator/ops/model.py deleted file mode 100644 index 3d19ba8b..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/model.py +++ /dev/null @@ -1,915 +0,0 @@ -# Copyright 2019 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. - -import json -import weakref -import os -import shutil -import tempfile -import time -import datetime -import re -import ipaddress -import decimal - -from abc import ABC, abstractmethod -from collections.abc import Mapping, MutableMapping -from pathlib import Path -from subprocess import run, PIPE, CalledProcessError - - -class Model: - - def __init__(self, unit_name, meta, backend): - self._cache = _ModelCache(backend) - self._backend = backend - self.unit = self.get_unit(unit_name) - self.app = self.unit.app - self.relations = RelationMapping(meta.relations, self.unit, self._backend, self._cache) - self.config = ConfigData(self._backend) - self.resources = Resources(list(meta.resources), self._backend) - self.pod = Pod(self._backend) - self.storages = StorageMapping(list(meta.storages), self._backend) - self._bindings = BindingMapping(self._backend) - - def get_unit(self, unit_name): - return self._cache.get(Unit, unit_name) - - def get_app(self, app_name): - return self._cache.get(Application, app_name) - - def get_relation(self, relation_name, relation_id=None): - """Get a specific Relation instance. - - If relation_id is given, this will return that Relation instance. - - If relation_id is not given, this will return the Relation instance if the - relation is established only once or None if it is not established. If this - same relation is established multiple times the error TooManyRelatedAppsError is raised. - """ - return self.relations._get_unique(relation_name, relation_id) - - def get_binding(self, binding_key): - """Get a network space binding. - - binding_key -- The relation name or instance to obtain bindings for. - - If binding_key is a relation name, the method returns the default binding for that - relation. If a relation instance is provided, the method first looks up a more specific - binding for that specific relation ID, and if none is found falls back to the default - binding for the relation name. - """ - return self._bindings.get(binding_key) - - -class _ModelCache: - - def __init__(self, backend): - self._backend = backend - self._weakrefs = weakref.WeakValueDictionary() - - def get(self, entity_type, *args): - key = (entity_type,) + args - entity = self._weakrefs.get(key) - if entity is None: - entity = entity_type(*args, backend=self._backend, cache=self) - self._weakrefs[key] = entity - return entity - - -class Application: - - def __init__(self, name, backend, cache): - self.name = name - self._backend = backend - self._cache = cache - self._is_our_app = self.name == self._backend.app_name - self._status = None - - @property - def status(self): - if not self._is_our_app: - return UnknownStatus() - - if not self._backend.is_leader(): - raise RuntimeError('cannot get application status as a non-leader unit') - - if self._status: - return self._status - - s = self._backend.status_get(is_app=True) - self._status = StatusBase.from_name(s['status'], s['message']) - return self._status - - @status.setter - def status(self, value): - if not isinstance(value, StatusBase): - raise InvalidStatusError( - 'invalid value provided for application {} status: {}'.format(self, value) - ) - - if not self._is_our_app: - raise RuntimeError('cannot to set status for a remote application {}'.format(self)) - - if not self._backend.is_leader(): - raise RuntimeError('cannot set application status as a non-leader unit') - - self._backend.status_set(value.name, value.message, is_app=True) - self._status = value - - def __repr__(self): - return '<{}.{} {}>'.format(type(self).__module__, type(self).__name__, self.name) - - -class Unit: - - def __init__(self, name, backend, cache): - self.name = name - - app_name = name.split('/')[0] - self.app = cache.get(Application, app_name) - - self._backend = backend - self._cache = cache - self._is_our_unit = self.name == self._backend.unit_name - self._status = None - - @property - def status(self): - if not self._is_our_unit: - return UnknownStatus() - - if self._status: - return self._status - - s = self._backend.status_get(is_app=False) - self._status = StatusBase.from_name(s['status'], s['message']) - return self._status - - @status.setter - def status(self, value): - if not isinstance(value, StatusBase): - raise InvalidStatusError( - 'invalid value provided for unit {} status: {}'.format(self, value) - ) - - if not self._is_our_unit: - raise RuntimeError('cannot set status for a remote unit {}'.format(self)) - - self._backend.status_set(value.name, value.message, is_app=False) - self._status = value - - def __repr__(self): - return '<{}.{} {}>'.format(type(self).__module__, type(self).__name__, self.name) - - def is_leader(self): - if self._is_our_unit: - # This value is not cached as it is not guaranteed to persist for the whole duration - # of a hook execution. - return self._backend.is_leader() - else: - raise RuntimeError( - 'cannot determine leadership status for remote applications: {}'.format(self) - ) - - def set_workload_version(self, version): - """Record the version of the software running as the workload. - - This shouldn't be confused with the revision of the charm. This is informative only; - shown in the output of 'juju status'. - """ - if not isinstance(version, str): - raise TypeError("workload version must be a str, not {}: {!r}".format( - type(version).__name__, version)) - self._backend.application_version_set(version) - - -class LazyMapping(Mapping, ABC): - - _lazy_data = None - - @abstractmethod - def _load(self): - raise NotImplementedError() - - @property - def _data(self): - data = self._lazy_data - if data is None: - data = self._lazy_data = self._load() - return data - - def _invalidate(self): - self._lazy_data = None - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, key): - return self._data[key] - - -class RelationMapping(Mapping): - """Map of relation names to lists of Relation instances.""" - - def __init__(self, relations_meta, our_unit, backend, cache): - self._peers = set() - for name, relation_meta in relations_meta.items(): - if relation_meta.role == 'peers': - self._peers.add(name) - self._our_unit = our_unit - self._backend = backend - self._cache = cache - self._data = {relation_name: None for relation_name in relations_meta} - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, relation_name): - is_peer = relation_name in self._peers - relation_list = self._data[relation_name] - if relation_list is None: - relation_list = self._data[relation_name] = [] - for rid in self._backend.relation_ids(relation_name): - relation = Relation(relation_name, rid, is_peer, - self._our_unit, self._backend, self._cache) - relation_list.append(relation) - return relation_list - - def _invalidate(self, relation_name): - self._data[relation_name] = None - - def _get_unique(self, relation_name, relation_id=None): - if relation_id is not None: - if not isinstance(relation_id, int): - raise ModelError('relation id {} must be int or None not {}'.format( - relation_id, - type(relation_id).__name__)) - for relation in self[relation_name]: - if relation.id == relation_id: - return relation - else: - # The relation may be dead, but it is not forgotten. - is_peer = relation_name in self._peers - return Relation(relation_name, relation_id, is_peer, - self._our_unit, self._backend, self._cache) - num_related = len(self[relation_name]) - if num_related == 0: - return None - elif num_related == 1: - return self[relation_name][0] - else: - # TODO: We need something in the framework to catch and gracefully handle - # errors, ideally integrating the error catching with Juju's mechanisms. - raise TooManyRelatedAppsError(relation_name, num_related, 1) - - -class BindingMapping: - - def __init__(self, backend): - self._backend = backend - self._data = {} - - def get(self, binding_key): - if isinstance(binding_key, Relation): - binding_name = binding_key.name - relation_id = binding_key.id - elif isinstance(binding_key, str): - binding_name = binding_key - relation_id = None - else: - raise ModelError('binding key must be str or relation instance, not {}' - ''.format(type(binding_key).__name__)) - binding = self._data.get(binding_key) - if binding is None: - binding = Binding(binding_name, relation_id, self._backend) - self._data[binding_key] = binding - return binding - - -class Binding: - """Binding to a network space.""" - - def __init__(self, name, relation_id, backend): - self.name = name - self._relation_id = relation_id - self._backend = backend - self._network = None - - @property - def network(self): - if self._network is None: - try: - self._network = Network(self._backend.network_get(self.name, self._relation_id)) - except RelationNotFoundError: - if self._relation_id is None: - raise - # If a relation is dead, we can still get network info associated with an - # endpoint itself - self._network = Network(self._backend.network_get(self.name)) - return self._network - - -class Network: - """Network space details.""" - - def __init__(self, network_info): - self.interfaces = [] - # Treat multiple addresses on an interface as multiple logical - # interfaces with the same name. - for interface_info in network_info['bind-addresses']: - interface_name = interface_info['interface-name'] - for address_info in interface_info['addresses']: - self.interfaces.append(NetworkInterface(interface_name, address_info)) - self.ingress_addresses = [] - for address in network_info['ingress-addresses']: - self.ingress_addresses.append(ipaddress.ip_address(address)) - self.egress_subnets = [] - for subnet in network_info['egress-subnets']: - self.egress_subnets.append(ipaddress.ip_network(subnet)) - - @property - def bind_address(self): - return self.interfaces[0].address - - @property - def ingress_address(self): - return self.ingress_addresses[0] - - -class NetworkInterface: - - def __init__(self, name, address_info): - self.name = name - # TODO: expose a hardware address here, see LP: #1864070. - self.address = ipaddress.ip_address(address_info['value']) - cidr = address_info['cidr'] - if not cidr: - # The cidr field may be empty, see LP: #1864102. - # In this case, make it a /32 or /128 IP network. - self.subnet = ipaddress.ip_network(address_info['value']) - else: - self.subnet = ipaddress.ip_network(cidr) - # TODO: expose a hostname/canonical name for the address here, see LP: #1864086. - - -class Relation: - def __init__(self, relation_name, relation_id, is_peer, our_unit, backend, cache): - self.name = relation_name - self.id = relation_id - self.app = None - self.units = set() - - # For peer relations, both the remote and the local app are the same. - if is_peer: - self.app = our_unit.app - try: - for unit_name in backend.relation_list(self.id): - unit = cache.get(Unit, unit_name) - self.units.add(unit) - if self.app is None: - self.app = unit.app - except RelationNotFoundError: - # If the relation is dead, just treat it as if it has no remote units. - pass - self.data = RelationData(self, our_unit, backend) - - def __repr__(self): - return '<{}.{} {}:{}>'.format(type(self).__module__, - type(self).__name__, - self.name, - self.id) - - -class RelationData(Mapping): - def __init__(self, relation, our_unit, backend): - self.relation = weakref.proxy(relation) - self._data = { - our_unit: RelationDataContent(self.relation, our_unit, backend), - our_unit.app: RelationDataContent(self.relation, our_unit.app, backend), - } - self._data.update({ - unit: RelationDataContent(self.relation, unit, backend) - for unit in self.relation.units}) - # The relation might be dead so avoid a None key here. - if self.relation.app is not None: - self._data.update({ - self.relation.app: RelationDataContent(self.relation, self.relation.app, backend), - }) - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, key): - return self._data[key] - - -# We mix in MutableMapping here to get some convenience implementations, but whether it's actually -# mutable or not is controlled by the flag. -class RelationDataContent(LazyMapping, MutableMapping): - - def __init__(self, relation, entity, backend): - self.relation = relation - self._entity = entity - self._backend = backend - self._is_app = isinstance(entity, Application) - - def _load(self): - try: - return self._backend.relation_get(self.relation.id, self._entity.name, self._is_app) - except RelationNotFoundError: - # Dead relations tell no tales (and have no data). - return {} - - def _is_mutable(self): - if self._is_app: - is_our_app = self._backend.app_name == self._entity.name - if not is_our_app: - return False - # Whether the application data bag is mutable or not depends on - # whether this unit is a leader or not, but this is not guaranteed - # to be always true during the same hook execution. - return self._backend.is_leader() - else: - is_our_unit = self._backend.unit_name == self._entity.name - if is_our_unit: - return True - return False - - def __setitem__(self, key, value): - if not self._is_mutable(): - raise RelationDataError('cannot set relation data for {}'.format(self._entity.name)) - if not isinstance(value, str): - raise RelationDataError('relation data values must be strings') - - self._backend.relation_set(self.relation.id, key, value, self._is_app) - - # Don't load data unnecessarily if we're only updating. - if self._lazy_data is not None: - if value == '': - # Match the behavior of Juju, which is that setting the value to an - # empty string will remove the key entirely from the relation data. - del self._data[key] - else: - self._data[key] = value - - def __delitem__(self, key): - # Match the behavior of Juju, which is that setting the value to an empty - # string will remove the key entirely from the relation data. - self.__setitem__(key, '') - - -class ConfigData(LazyMapping): - - def __init__(self, backend): - self._backend = backend - - def _load(self): - return self._backend.config_get() - - -class StatusBase: - """Status values specific to applications and units.""" - - _statuses = {} - - def __init__(self, message): - self.message = message - - def __new__(cls, *args, **kwargs): - if cls is StatusBase: - raise TypeError("cannot instantiate a base class") - cls._statuses[cls.name] = cls - return super().__new__(cls) - - @classmethod - def from_name(cls, name, message): - return cls._statuses[name](message) - - -class ActiveStatus(StatusBase): - """The unit is ready. - - The unit believes it is correctly offering all the services it has been asked to offer. - """ - name = 'active' - - def __init__(self, message=None): - super().__init__(message or '') - - -class BlockedStatus(StatusBase): - """The unit requires manual intervention. - - An operator has to manually intervene to unblock the unit and let it proceed. - """ - name = 'blocked' - - -class MaintenanceStatus(StatusBase): - """The unit is performing maintenance tasks. - - The unit is not yet providing services, but is actively doing work in preparation - for providing those services. This is a "spinning" state, not an error state. It - reflects activity on the unit itself, not on peers or related units. - - """ - name = 'maintenance' - - -class UnknownStatus(StatusBase): - """The unit status is unknown. - - A unit-agent has finished calling install, config-changed and start, but the - charm has not called status-set yet. - - """ - name = 'unknown' - - def __init__(self): - # Unknown status cannot be set and does not have a message associated with it. - super().__init__('') - - -class WaitingStatus(StatusBase): - """A unit is unable to progress. - - The unit is unable to progress to an active state because an application to which - it is related is not running. - - """ - name = 'waiting' - - -class Resources: - """Object representing resources for the charm. - """ - - def __init__(self, names, backend): - self._backend = backend - self._paths = {name: None for name in names} - - def fetch(self, name): - """Fetch the resource from the controller or store. - - If successfully fetched, this returns a Path object to where the resource is stored - on disk, otherwise it raises a ModelError. - """ - if name not in self._paths: - raise RuntimeError('invalid resource name: {}'.format(name)) - if self._paths[name] is None: - self._paths[name] = Path(self._backend.resource_get(name)) - return self._paths[name] - - -class Pod: - def __init__(self, backend): - self._backend = backend - - def set_spec(self, spec, k8s_resources=None): - if not self._backend.is_leader(): - raise ModelError('cannot set a pod spec as this unit is not a leader') - self._backend.pod_spec_set(spec, k8s_resources) - - -class StorageMapping(Mapping): - """Map of storage names to lists of Storage instances.""" - - def __init__(self, storage_names, backend): - self._backend = backend - self._storage_map = {storage_name: None for storage_name in storage_names} - - def __contains__(self, key): - return key in self._storage_map - - def __len__(self): - return len(self._storage_map) - - def __iter__(self): - return iter(self._storage_map) - - def __getitem__(self, storage_name): - storage_list = self._storage_map[storage_name] - if storage_list is None: - storage_list = self._storage_map[storage_name] = [] - for storage_id in self._backend.storage_list(storage_name): - storage_list.append(Storage(storage_name, storage_id, self._backend)) - return storage_list - - def request(self, storage_name, count=1): - """Requests new storage instances of a given name. - - Uses storage-add tool to request additional storage. Juju will notify the unit - via -storage-attached events when it becomes available. - """ - if storage_name not in self._storage_map: - raise ModelError(('cannot add storage {!r}:' - ' it is not present in the charm metadata').format(storage_name)) - self._backend.storage_add(storage_name, count) - - -class Storage: - - def __init__(self, storage_name, storage_id, backend): - self.name = storage_name - self.id = storage_id - self._backend = backend - self._location = None - - @property - def location(self): - if self._location is None: - raw = self._backend.storage_get('{}/{}'.format(self.name, self.id), "location") - self._location = Path(raw) - return self._location - - -class ModelError(Exception): - pass - - -class TooManyRelatedAppsError(ModelError): - def __init__(self, relation_name, num_related, max_supported): - super().__init__('Too many remote applications on {} ({} > {})'.format( - relation_name, num_related, max_supported)) - self.relation_name = relation_name - self.num_related = num_related - self.max_supported = max_supported - - -class RelationDataError(ModelError): - pass - - -class RelationNotFoundError(ModelError): - pass - - -class InvalidStatusError(ModelError): - pass - - -class ModelBackend: - - LEASE_RENEWAL_PERIOD = datetime.timedelta(seconds=30) - - def __init__(self): - self.unit_name = os.environ['JUJU_UNIT_NAME'] - self.app_name = self.unit_name.split('/')[0] - - self._is_leader = None - self._leader_check_time = None - - def _run(self, *args, return_output=False, use_json=False): - kwargs = dict(stdout=PIPE, stderr=PIPE) - if use_json: - args += ('--format=json',) - try: - result = run(args, check=True, **kwargs) - except CalledProcessError as e: - raise ModelError(e.stderr) - if return_output: - if result.stdout is None: - return '' - else: - text = result.stdout.decode('utf8') - if use_json: - return json.loads(text) - else: - return text - - def relation_ids(self, relation_name): - relation_ids = self._run('relation-ids', relation_name, return_output=True, use_json=True) - return [int(relation_id.split(':')[-1]) for relation_id in relation_ids] - - def relation_list(self, relation_id): - try: - return self._run('relation-list', '-r', str(relation_id), - return_output=True, use_json=True) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def relation_get(self, relation_id, member_name, is_app): - if not isinstance(is_app, bool): - raise TypeError('is_app parameter to relation_get must be a boolean') - - try: - return self._run('relation-get', '-r', str(relation_id), - '-', member_name, '--app={}'.format(is_app), - return_output=True, use_json=True) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def relation_set(self, relation_id, key, value, is_app): - if not isinstance(is_app, bool): - raise TypeError('is_app parameter to relation_set must be a boolean') - - try: - return self._run('relation-set', '-r', str(relation_id), - '{}={}'.format(key, value), '--app={}'.format(is_app)) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def config_get(self): - return self._run('config-get', return_output=True, use_json=True) - - def is_leader(self): - """Obtain the current leadership status for the unit the charm code is executing on. - - The value is cached for the duration of a lease which is 30s in Juju. - """ - now = time.monotonic() - if self._leader_check_time is None: - check = True - else: - time_since_check = datetime.timedelta(seconds=now - self._leader_check_time) - check = (time_since_check > self.LEASE_RENEWAL_PERIOD or self._is_leader is None) - if check: - # Current time MUST be saved before running is-leader to ensure the cache - # is only used inside the window that is-leader itself asserts. - self._leader_check_time = now - self._is_leader = self._run('is-leader', return_output=True, use_json=True) - - return self._is_leader - - def resource_get(self, resource_name): - return self._run('resource-get', resource_name, return_output=True).strip() - - def pod_spec_set(self, spec, k8s_resources): - tmpdir = Path(tempfile.mkdtemp('-pod-spec-set')) - try: - spec_path = tmpdir / 'spec.json' - spec_path.write_text(json.dumps(spec)) - args = ['--file', str(spec_path)] - if k8s_resources: - k8s_res_path = tmpdir / 'k8s-resources.json' - k8s_res_path.write_text(json.dumps(k8s_resources)) - args.extend(['--k8s-resources', str(k8s_res_path)]) - self._run('pod-spec-set', *args) - finally: - shutil.rmtree(str(tmpdir)) - - def status_get(self, *, is_app=False): - """Get a status of a unit or an application. - - app -- A boolean indicating whether the status should be retrieved for a unit - or an application. - """ - return self._run('status-get', '--include-data', '--application={}'.format(is_app)) - - def status_set(self, status, message='', *, is_app=False): - """Set a status of a unit or an application. - - app -- A boolean indicating whether the status should be set for a unit or an - application. - """ - if not isinstance(is_app, bool): - raise TypeError('is_app parameter must be boolean') - return self._run('status-set', '--application={}'.format(is_app), status, message) - - def storage_list(self, name): - return [int(s.split('/')[1]) for s in self._run('storage-list', name, - return_output=True, use_json=True)] - - def storage_get(self, storage_name_id, attribute): - return self._run('storage-get', '-s', storage_name_id, attribute, - return_output=True, use_json=True) - - def storage_add(self, name, count=1): - if not isinstance(count, int) or isinstance(count, bool): - raise TypeError('storage count must be integer, got: {} ({})'.format(count, - type(count))) - self._run('storage-add', '{}={}'.format(name, count)) - - def action_get(self): - return self._run('action-get', return_output=True, use_json=True) - - def action_set(self, results): - self._run('action-set', *["{}={}".format(k, v) for k, v in results.items()]) - - def action_log(self, message): - self._run('action-log', message) - - def action_fail(self, message=''): - self._run('action-fail', message) - - def application_version_set(self, version): - self._run('application-version-set', '--', version) - - def juju_log(self, level, message): - self._run('juju-log', '--log-level', level, message) - - def network_get(self, binding_name, relation_id=None): - """Return network info provided by network-get for a given binding. - - binding_name -- A name of a binding (relation name or extra-binding name). - relation_id -- An optional relation id to get network info for. - """ - cmd = ['network-get', binding_name] - if relation_id is not None: - cmd.extend(['-r', str(relation_id)]) - try: - return self._run(*cmd, return_output=True, use_json=True) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def add_metrics(self, metrics, labels=None): - cmd = ['add-metric'] - - if labels: - label_args = [] - for k, v in labels.items(): - _ModelBackendValidator.validate_metric_label(k) - _ModelBackendValidator.validate_label_value(k, v) - label_args.append('{}={}'.format(k, v)) - cmd.extend(['--labels', ','.join(label_args)]) - - metric_args = [] - for k, v in metrics.items(): - _ModelBackendValidator.validate_metric_key(k) - metric_value = _ModelBackendValidator.format_metric_value(v) - metric_args.append('{}={}'.format(k, metric_value)) - cmd.extend(metric_args) - self._run(*cmd) - - -class _ModelBackendValidator: - """Provides facilities for validating inputs and formatting them for model backends.""" - - METRIC_KEY_REGEX = re.compile(r'^[a-zA-Z](?:[a-zA-Z0-9-_]*[a-zA-Z0-9])?$') - - @classmethod - def validate_metric_key(cls, key): - if cls.METRIC_KEY_REGEX.match(key) is None: - raise ModelError( - 'invalid metric key {!r}: must match {}'.format( - key, cls.METRIC_KEY_REGEX.pattern)) - - @classmethod - def validate_metric_label(cls, label_name): - if cls.METRIC_KEY_REGEX.match(label_name) is None: - raise ModelError( - 'invalid metric label name {!r}: must match {}'.format( - label_name, cls.METRIC_KEY_REGEX.pattern)) - - @classmethod - def format_metric_value(cls, value): - try: - decimal_value = decimal.Decimal.from_float(value) - except TypeError as e: - e2 = ModelError('invalid metric value {!r} provided:' - ' must be a positive finite float'.format(value)) - raise e2 from e - if decimal_value.is_nan() or decimal_value.is_infinite() or decimal_value < 0: - raise ModelError('invalid metric value {!r} provided:' - ' must be a positive finite float'.format(value)) - return str(decimal_value) - - @classmethod - def validate_label_value(cls, label, value): - # Label values cannot be empty, contain commas or equal signs as those are - # used by add-metric as separators. - if not value: - raise ModelError( - 'metric label {} has an empty value, which is not allowed'.format(label)) - v = str(value) - if re.search('[,=]', v) is not None: - raise ModelError( - 'metric label values must not contain "," or "=": {}={!r}'.format(label, value)) diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/testing.py b/magma/squid_cnf/charms/squid/mod/operator/ops/testing.py deleted file mode 100644 index 72d840c4..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/testing.py +++ /dev/null @@ -1,477 +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. - -import inspect -import pathlib -from textwrap import dedent -import typing - -from ops import charm, framework, model - - -# OptionalYAML is something like metadata.yaml or actions.yaml. You can -# pass in a file-like object or the string directly. -OptionalYAML = typing.Optional[typing.Union[str, typing.TextIO]] - - -# noinspection PyProtectedMember -class Harness: - """This class represents a way to build up the model that will drive a test suite. - - The model that is created is from the viewpoint of the charm that you are testing. - - Example:: - - harness = Harness(MyCharm) - # Do initial setup here - relation_id = harness.add_relation('db', 'postgresql') - # Now instantiate the charm to see events as the model changes - harness.begin() - harness.add_relation_unit(relation_id, 'postgresql/0') - harness.update_relation_data(relation_id, 'postgresql/0', {'key': 'val'}) - # Check that charm has properly handled the relation_joined event for postgresql/0 - self.assertEqual(harness.charm. ...) - - Args: - charm_cls: The Charm class that you'll be testing. - meta: charm.CharmBase is a A string or file-like object containing the contents of - metadata.yaml. If not supplied, we will look for a 'metadata.yaml' file in the - parent directory of the Charm, and if not found fall back to a trivial - 'name: test-charm' metadata. - actions: A string or file-like object containing the contents of - actions.yaml. If not supplied, we will look for a 'actions.yaml' file in the - parent directory of the Charm. - """ - - def __init__( - self, - charm_cls: typing.Type[charm.CharmBase], - *, - meta: OptionalYAML = None, - actions: OptionalYAML = None): - # TODO: jam 2020-03-05 We probably want to take config as a parameter as well, since - # it would define the default values of config that the charm would see. - self._charm_cls = charm_cls - self._charm = None - self._charm_dir = 'no-disk-path' # this may be updated by _create_meta - self._meta = self._create_meta(meta, actions) - self._unit_name = self._meta.name + '/0' - self._framework = None - self._hooks_enabled = True - self._relation_id_counter = 0 - self._backend = _TestingModelBackend(self._unit_name, self._meta) - self._model = model.Model(self._unit_name, self._meta, self._backend) - self._framework = framework.Framework(":memory:", self._charm_dir, self._meta, self._model) - - @property - def charm(self) -> charm.CharmBase: - """Return the instance of the charm class that was passed to __init__. - - Note that the Charm is not instantiated until you have called - :meth:`.begin()`. - """ - return self._charm - - @property - def model(self) -> model.Model: - """Return the :class:`~ops.model.Model` that is being driven by this Harness.""" - return self._model - - @property - def framework(self) -> framework.Framework: - """Return the Framework that is being driven by this Harness.""" - return self._framework - - def begin(self) -> None: - """Instantiate the Charm and start handling events. - - Before calling begin(), there is no Charm instance, so changes to the Model won't emit - events. You must call begin before :attr:`.charm` is valid. - """ - if self._charm is not None: - raise RuntimeError('cannot call the begin method on the harness more than once') - - # The Framework adds attributes to class objects for events, etc. As such, we can't re-use - # the original class against multiple Frameworks. So create a locally defined class - # and register it. - # TODO: jam 2020-03-16 We are looking to changes this to Instance attributes instead of - # Class attributes which should clean up this ugliness. The API can stay the same - class TestEvents(self._charm_cls.on.__class__): - pass - - TestEvents.__name__ = self._charm_cls.on.__class__.__name__ - - class TestCharm(self._charm_cls): - on = TestEvents() - - # Note: jam 2020-03-01 This is so that errors in testing say MyCharm has no attribute foo, - # rather than TestCharm has no attribute foo. - TestCharm.__name__ = self._charm_cls.__name__ - self._charm = TestCharm(self._framework, self._framework.meta.name) - - def _create_meta(self, charm_metadata, action_metadata): - """Create a CharmMeta object. - - Handle the cases where a user doesn't supply explicit metadata snippets. - """ - filename = inspect.getfile(self._charm_cls) - charm_dir = pathlib.Path(filename).parents[1] - - if charm_metadata is None: - metadata_path = charm_dir / 'metadata.yaml' - if metadata_path.is_file(): - charm_metadata = metadata_path.read_text() - self._charm_dir = charm_dir - else: - # The simplest of metadata that the framework can support - charm_metadata = 'name: test-charm' - elif isinstance(charm_metadata, str): - charm_metadata = dedent(charm_metadata) - - if action_metadata is None: - actions_path = charm_dir / 'actions.yaml' - if actions_path.is_file(): - action_metadata = actions_path.read_text() - self._charm_dir = charm_dir - elif isinstance(action_metadata, str): - action_metadata = dedent(action_metadata) - - return charm.CharmMeta.from_yaml(charm_metadata, action_metadata) - - def disable_hooks(self) -> None: - """Stop emitting hook events when the model changes. - - This can be used by developers to stop changes to the model from emitting events that - the charm will react to. Call :meth:`.enable_hooks` - to re-enable them. - """ - self._hooks_enabled = False - - def enable_hooks(self) -> None: - """Re-enable hook events from charm.on when the model is changed. - - By default hook events are enabled once you call :meth:`.begin`, - but if you have used :meth:`.disable_hooks`, this can be used to - enable them again. - """ - self._hooks_enabled = True - - def _next_relation_id(self): - rel_id = self._relation_id_counter - self._relation_id_counter += 1 - return rel_id - - def add_relation(self, relation_name: str, remote_app: str) -> int: - """Declare that there is a new relation between this app and `remote_app`. - - Args: - relation_name: The relation on Charm that is being related to - remote_app: The name of the application that is being related to - - Return: - The relation_id created by this add_relation. - """ - rel_id = self._next_relation_id() - self._backend._relation_ids_map.setdefault(relation_name, []).append(rel_id) - self._backend._relation_names[rel_id] = relation_name - self._backend._relation_list_map[rel_id] = [] - self._backend._relation_data[rel_id] = { - remote_app: {}, - self._backend.unit_name: {}, - self._backend.app_name: {}, - } - # Reload the relation_ids list - if self._model is not None: - self._model.relations._invalidate(relation_name) - if self._charm is None or not self._hooks_enabled: - return rel_id - relation = self._model.get_relation(relation_name, rel_id) - app = self._model.get_app(remote_app) - self._charm.on[relation_name].relation_created.emit( - relation, app) - return rel_id - - def add_relation_unit(self, relation_id: int, remote_unit_name: str) -> None: - """Add a new unit to a relation. - - Example:: - - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - - This will trigger a `relation_joined` event and a `relation_changed` event. - - Args: - relation_id: The integer relation identifier (as returned by add_relation). - remote_unit_name: A string representing the remote unit that is being added. - Return: - None - """ - self._backend._relation_list_map[relation_id].append(remote_unit_name) - self._backend._relation_data[relation_id][remote_unit_name] = {} - relation_name = self._backend._relation_names[relation_id] - # Make sure that the Model reloads the relation_list for this relation_id, as well as - # reloading the relation data for this unit. - if self._model is not None: - self._model.relations._invalidate(relation_name) - remote_unit = self._model.get_unit(remote_unit_name) - relation = self._model.get_relation(relation_name, relation_id) - relation.data[remote_unit]._invalidate() - if self._charm is None or not self._hooks_enabled: - return - self._charm.on[relation_name].relation_joined.emit( - relation, remote_unit.app, remote_unit) - - def get_relation_data(self, relation_id: int, app_or_unit: str) -> typing.Mapping: - """Get the relation data bucket for a single app or unit in a given relation. - - This ignores all of the safety checks of who can and can't see data in relations (eg, - non-leaders can't read their own application's relation data because there are no events - that keep that data up-to-date for the unit). - - Args: - relation_id: The relation whose content we want to look at. - app_or_unit: The name of the application or unit whose data we want to read - Return: - a dict containing the relation data for `app_or_unit` or None. - Raises: - KeyError: if relation_id doesn't exist - """ - return self._backend._relation_data[relation_id].get(app_or_unit, None) - - def get_workload_version(self) -> str: - """Read the workload version that was set by the unit.""" - return self._backend._workload_version - - def update_relation_data( - self, - relation_id: int, - app_or_unit: str, - key_values: typing.Mapping, - ) -> None: - """Update the relation data for a given unit or application in a given relation. - - This also triggers the `relation_changed` event for this relation_id. - - Args: - relation_id: The integer relation_id representing this relation. - app_or_unit: The unit or application name that is being updated. - This can be the local or remote application. - key_values: Each key/value will be updated in the relation data. - """ - relation_name = self._backend._relation_names[relation_id] - relation = self._model.get_relation(relation_name, relation_id) - if '/' in app_or_unit: - entity = self._model.get_unit(app_or_unit) - else: - entity = self._model.get_app(app_or_unit) - rel_data = relation.data.get(entity, None) - if rel_data is not None: - # rel_data may have cached now-stale data, so _invalidate() it. - # Note, this won't cause the data to be loaded if it wasn't already. - rel_data._invalidate() - - new_values = self._backend._relation_data[relation_id][app_or_unit].copy() - for k, v in key_values.items(): - if v == '': - new_values.pop(k, None) - else: - new_values[k] = v - self._backend._relation_data[relation_id][app_or_unit] = new_values - - if app_or_unit == self._model.unit.name: - # No events for our own unit - return - if app_or_unit == self._model.app.name: - # updating our own app only generates an event if it is a peer relation and we - # aren't the leader - is_peer = self._meta.relations[relation_name].role == 'peers' - if not is_peer: - return - if self._model.unit.is_leader(): - return - self._emit_relation_changed(relation_id, app_or_unit) - - def _emit_relation_changed(self, relation_id, app_or_unit): - if self._charm is None or not self._hooks_enabled: - return - rel_name = self._backend._relation_names[relation_id] - relation = self.model.get_relation(rel_name, relation_id) - if '/' in app_or_unit: - app_name = app_or_unit.split('/')[0] - unit_name = app_or_unit - app = self.model.get_app(app_name) - unit = self.model.get_unit(unit_name) - args = (relation, app, unit) - else: - app_name = app_or_unit - app = self.model.get_app(app_name) - args = (relation, app) - self._charm.on[rel_name].relation_changed.emit(*args) - - def update_config( - self, - key_values: typing.Mapping[str, str] = None, - unset: typing.Iterable[str] = (), - ) -> None: - """Update the config as seen by the charm. - - This will trigger a `config_changed` event. - - Args: - key_values: A Mapping of key:value pairs to update in config. - unset: An iterable of keys to remove from Config. (Note that this does - not currently reset the config values to the default defined in config.yaml.) - """ - config = self._backend._config - if key_values is not None: - for key, value in key_values.items(): - config[key] = value - for key in unset: - config.pop(key, None) - # NOTE: jam 2020-03-01 Note that this sort of works "by accident". Config - # is a LazyMapping, but its _load returns a dict and this method mutates - # the dict that Config is caching. Arguably we should be doing some sort - # of charm.framework.model.config._invalidate() - if self._charm is None or not self._hooks_enabled: - return - self._charm.on.config_changed.emit() - - def set_leader(self, is_leader: bool = True) -> None: - """Set whether this unit is the leader or not. - - If this charm becomes a leader then `leader_elected` will be triggered. - - Args: - is_leader: True/False as to whether this unit is the leader. - """ - was_leader = self._backend._is_leader - self._backend._is_leader = is_leader - # Note: jam 2020-03-01 currently is_leader is cached at the ModelBackend level, not in - # the Model objects, so this automatically gets noticed. - if is_leader and not was_leader and self._charm is not None and self._hooks_enabled: - self._charm.on.leader_elected.emit() - - -class _TestingModelBackend: - """This conforms to the interface for ModelBackend but provides canned data. - - DO NOT use this class directly, it is used by `Harness`_ to drive the model. - `Harness`_ is responsible for maintaining the internal consistency of the values here, - as the only public methods of this type are for implementing ModelBackend. - """ - - def __init__(self, unit_name, meta): - self.unit_name = unit_name - self.app_name = self.unit_name.split('/')[0] - self._calls = [] - self._meta = meta - self._is_leader = None - self._relation_ids_map = {} # relation name to [relation_ids,...] - self._relation_names = {} # reverse map from relation_id to relation_name - self._relation_list_map = {} # relation_id: [unit_name,...] - self._relation_data = {} # {relation_id: {name: data}} - self._config = {} - self._is_leader = False - self._resources_map = {} - self._pod_spec = None - self._app_status = None - self._unit_status = None - self._workload_version = None - - def relation_ids(self, relation_name): - try: - return self._relation_ids_map[relation_name] - except KeyError as e: - if relation_name not in self._meta.relations: - raise model.ModelError('{} is not a known relation'.format(relation_name)) from e - return [] - - def relation_list(self, relation_id): - try: - return self._relation_list_map[relation_id] - except KeyError as e: - raise model.RelationNotFoundError from e - - def relation_get(self, relation_id, member_name, is_app): - if is_app and '/' in member_name: - member_name = member_name.split('/')[0] - if relation_id not in self._relation_data: - raise model.RelationNotFoundError() - return self._relation_data[relation_id][member_name].copy() - - def relation_set(self, relation_id, key, value, is_app): - relation = self._relation_data[relation_id] - if is_app: - bucket_key = self.app_name - else: - bucket_key = self.unit_name - if bucket_key not in relation: - relation[bucket_key] = {} - bucket = relation[bucket_key] - if value == '': - bucket.pop(key, None) - else: - bucket[key] = value - - def config_get(self): - return self._config - - def is_leader(self): - return self._is_leader - - def application_version_set(self, version): - self._workload_version = version - - def resource_get(self, resource_name): - return self._resources_map[resource_name] - - def pod_spec_set(self, spec, k8s_resources): - self._pod_spec = (spec, k8s_resources) - - def status_get(self, *, is_app=False): - if is_app: - return self._app_status - else: - return self._unit_status - - def status_set(self, status, message='', *, is_app=False): - if is_app: - self._app_status = (status, message) - else: - self._unit_status = (status, message) - - def storage_list(self, name): - raise NotImplementedError(self.storage_list) - - def storage_get(self, storage_name_id, attribute): - raise NotImplementedError(self.storage_get) - - def storage_add(self, name, count=1): - raise NotImplementedError(self.storage_add) - - def action_get(self): - raise NotImplementedError(self.action_get) - - def action_set(self, results): - raise NotImplementedError(self.action_set) - - def action_log(self, message): - raise NotImplementedError(self.action_log) - - def action_fail(self, message=''): - raise NotImplementedError(self.action_fail) - - def network_get(self, endpoint_name, relation_id=None): - raise NotImplementedError(self.network_get) diff --git a/magma/squid_cnf/charms/squid/mod/operator/requirements.txt b/magma/squid_cnf/charms/squid/mod/operator/requirements.txt deleted file mode 100644 index 5500f007..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -PyYAML diff --git a/magma/squid_cnf/charms/squid/mod/operator/run_tests b/magma/squid_cnf/charms/squid/mod/operator/run_tests deleted file mode 100755 index 56411030..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/run_tests +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -python3 -m unittest "$@" diff --git a/magma/squid_cnf/charms/squid/mod/operator/setup.py b/magma/squid_cnf/charms/squid/mod/operator/setup.py deleted file mode 100644 index cc017478..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/setup.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2019 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 setuptools import setup - -with open("README.md", "r") as fh: - long_description = fh.read() - -setup( - name="ops", - version="0.0.1", - description="The Python library behind great charms", - long_description=long_description, - long_description_content_type="text/markdown", - license="Apache-2.0", - url="https://github.com/canonical/operator", - packages=["ops"], - classifiers=[ - "Development Status :: 4 - Beta", - - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - - "License :: OSI Approved :: Apache Software License", - ], -) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/__init__.py b/magma/squid_cnf/charms/squid/mod/operator/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids b/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids deleted file mode 100755 index a7e0ead2..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -case $1 in - db) echo '["db:1"]' ;; - mon) echo '["mon:2"]' ;; - ha) echo '[]' ;; - db0) echo '[]' ;; - db1) echo '["db1:4"]' ;; - db2) echo '["db2:5", "db2:6"]' ;; - *) echo '[]' ;; -esac diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list b/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list deleted file mode 100755 index 88490159..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -fail_not_found() { - 1>&2 echo "ERROR invalid value \"$1\" for option -r: relation not found" - exit 2 -} - -case $2 in - 1) echo '["remote/0"]' ;; - 2) echo '["remote/0"]' ;; - 3) fail_not_found $2 ;; - 4) echo '["remoteapp1/0"]' ;; - 5) echo '["remoteapp1/0"]' ;; - 6) echo '["remoteapp2/0"]' ;; - *) fail_not_found $2 ;; -esac diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml deleted file mode 100644 index ffc01860..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml +++ /dev/null @@ -1 +0,0 @@ -"options": {} diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/__init__.py b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops deleted file mode 120000 index 1356790e..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops +++ /dev/null @@ -1 +0,0 @@ -../../../../ops \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml deleted file mode 100644 index 3b3aed87..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: main -summary: A charm used for testing the basic operation of the entrypoint code. -maintainer: Dmitrii Shcherbakov -description: A charm used for testing the basic operation of the entrypoint code. -tags: - - misc -series: - - bionic - - cosmic - - disco -min-juju-version: 2.7.1 -provides: - db: - interface: db -requires: - mon: - interface: monitoring -peers: - ha: - interface: cluster -subordinate: false -storage: - disks: - type: block - multiple: - range: 0- diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py deleted file mode 100755 index 0e066c97..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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. - -import os -import base64 -import pickle -import sys -import logging - -sys.path.append('lib') - -from ops.charm import CharmBase # noqa: E402 (module-level import after non-import code) -from ops.main import main # noqa: E402 (ditto) - -logger = logging.getLogger() - - -class Charm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - - # This environment variable controls the test charm behavior. - charm_config = os.environ.get('CHARM_CONFIG') - if charm_config is not None: - self._charm_config = pickle.loads(base64.b64decode(charm_config)) - else: - self._charm_config = {} - - # TODO: refactor to use StoredState - # (this implies refactoring most of test_main.py) - self._state_file = self._charm_config.get('STATE_FILE') - try: - with open(str(self._state_file), 'rb') as f: - self._state = pickle.load(f) - except (FileNotFoundError, EOFError): - self._state = { - 'on_install': [], - 'on_start': [], - 'on_config_changed': [], - 'on_update_status': [], - 'on_leader_settings_changed': [], - 'on_db_relation_joined': [], - 'on_mon_relation_changed': [], - 'on_mon_relation_departed': [], - 'on_ha_relation_broken': [], - 'on_foo_bar_action': [], - 'on_start_action': [], - 'on_collect_metrics': [], - - 'on_log_critical_action': [], - 'on_log_error_action': [], - 'on_log_warning_action': [], - 'on_log_info_action': [], - 'on_log_debug_action': [], - - # Observed event types per invocation. A list is used to preserve the - # order in which charm handlers have observed the events. - 'observed_event_types': [], - } - - self.framework.observe(self.on.install, self) - self.framework.observe(self.on.start, self) - self.framework.observe(self.on.config_changed, self) - self.framework.observe(self.on.update_status, self) - self.framework.observe(self.on.leader_settings_changed, self) - # Test relation events with endpoints from different - # sections (provides, requires, peers) as well. - self.framework.observe(self.on.db_relation_joined, self) - self.framework.observe(self.on.mon_relation_changed, self) - self.framework.observe(self.on.mon_relation_departed, self) - self.framework.observe(self.on.ha_relation_broken, self) - - if self._charm_config.get('USE_ACTIONS'): - self.framework.observe(self.on.start_action, self) - self.framework.observe(self.on.foo_bar_action, self) - - self.framework.observe(self.on.collect_metrics, self) - - if self._charm_config.get('USE_LOG_ACTIONS'): - self.framework.observe(self.on.log_critical_action, self) - self.framework.observe(self.on.log_error_action, self) - self.framework.observe(self.on.log_warning_action, self) - self.framework.observe(self.on.log_info_action, self) - self.framework.observe(self.on.log_debug_action, self) - - def _write_state(self): - """Write state variables so that the parent process can read them. - - Each invocation will override the previous state which is intentional. - """ - if self._state_file is not None: - with self._state_file.open('wb') as f: - pickle.dump(self._state, f) - - def on_install(self, event): - self._state['on_install'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_start(self, event): - self._state['on_start'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_config_changed(self, event): - self._state['on_config_changed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - event.defer() - self._write_state() - - def on_update_status(self, event): - self._state['on_update_status'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_leader_settings_changed(self, event): - self._state['on_leader_settings_changed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_db_relation_joined(self, event): - assert event.app is not None, 'application name cannot be None for a relation-joined event' - self._state['on_db_relation_joined'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['db_relation_joined_data'] = event.snapshot() - self._write_state() - - def on_mon_relation_changed(self, event): - assert event.app is not None, ( - 'application name cannot be None for a relation-changed event') - if os.environ.get('JUJU_REMOTE_UNIT'): - assert event.unit is not None, ( - 'a unit name cannot be None for a relation-changed event' - ' associated with a remote unit') - self._state['on_mon_relation_changed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['mon_relation_changed_data'] = event.snapshot() - self._write_state() - - def on_mon_relation_departed(self, event): - assert event.app is not None, ( - 'application name cannot be None for a relation-departed event') - self._state['on_mon_relation_departed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['mon_relation_departed_data'] = event.snapshot() - self._write_state() - - def on_ha_relation_broken(self, event): - assert event.app is None, ( - 'relation-broken events cannot have a reference to a remote application') - assert event.unit is None, ( - 'relation broken events cannot have a reference to a remote unit') - self._state['on_ha_relation_broken'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['ha_relation_broken_data'] = event.snapshot() - self._write_state() - - def on_start_action(self, event): - assert event.handle.kind == 'start_action', ( - 'event action name cannot be different from the one being handled') - self._state['on_start_action'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_foo_bar_action(self, event): - assert event.handle.kind == 'foo_bar_action', ( - 'event action name cannot be different from the one being handled') - self._state['on_foo_bar_action'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_collect_metrics(self, event): - self._state['on_collect_metrics'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - event.add_metrics({'foo': 42}, {'bar': 4.2}) - self._write_state() - - def on_log_critical_action(self, event): - logger.critical('super critical') - - def on_log_error_action(self, event): - logger.error('grave error') - - def on_log_warning_action(self, event): - logger.warning('wise warning') - - def on_log_info_action(self, event): - logger.info('useful info') - - def on_log_debug_action(self, event): - logger.debug('insightful debug') - - -if __name__ == '__main__': - main(Charm) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py deleted file mode 100755 index c8d84475..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/python3 -# Copyright 2019 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. - -import os -import unittest -import tempfile -import shutil - -from pathlib import Path - -from ops.charm import ( - CharmBase, - CharmMeta, - CharmEvents, -) -from ops.framework import Framework, EventSource, EventBase -from ops.model import Model, ModelBackend - -from .test_helpers import fake_script, fake_script_calls - - -class TestCharm(unittest.TestCase): - - def setUp(self): - def restore_env(env): - os.environ.clear() - os.environ.update(env) - self.addCleanup(restore_env, os.environ.copy()) - - os.environ['PATH'] = "{}:{}".format(Path(__file__).parent / 'bin', os.environ['PATH']) - os.environ['JUJU_UNIT_NAME'] = 'local/0' - - self.tmpdir = Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(self.tmpdir)) - self.meta = CharmMeta() - - class CustomEvent(EventBase): - pass - - class TestCharmEvents(CharmEvents): - custom = EventSource(CustomEvent) - - # Relations events are defined dynamically and modify the class attributes. - # We use a subclass temporarily to prevent these side effects from leaking. - CharmBase.on = TestCharmEvents() - - def cleanup(): - CharmBase.on = CharmEvents() - self.addCleanup(cleanup) - - def create_framework(self): - model = Model('local/0', self.meta, ModelBackend()) - framework = Framework(self.tmpdir / "framework.data", self.tmpdir, self.meta, model) - self.addCleanup(framework.close) - return framework - - def test_basic(self): - - class MyCharm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - - self.started = False - framework.observe(self.on.start, self) - - def on_start(self, event): - self.started = True - - events = list(MyCharm.on.events()) - self.assertIn('install', events) - self.assertIn('custom', events) - - framework = self.create_framework() - charm = MyCharm(framework, None) - charm.on.start.emit() - - self.assertEqual(charm.started, True) - - def test_helper_properties(self): - framework = self.create_framework() - - class MyCharm(CharmBase): - pass - - charm = MyCharm(framework, None) - self.assertEqual(charm.app, framework.model.app) - self.assertEqual(charm.unit, framework.model.unit) - self.assertEqual(charm.meta, framework.meta) - self.assertEqual(charm.charm_dir, framework.charm_dir) - - def test_relation_events(self): - - class MyCharm(CharmBase): - def __init__(self, *args): - super().__init__(*args) - self.seen = [] - for rel in ('req1', 'req-2', 'pro1', 'pro-2', 'peer1', 'peer-2'): - # Hook up relation events to generic handler. - self.framework.observe(self.on[rel].relation_joined, self.on_any_relation) - self.framework.observe(self.on[rel].relation_changed, self.on_any_relation) - self.framework.observe(self.on[rel].relation_departed, self.on_any_relation) - self.framework.observe(self.on[rel].relation_broken, self.on_any_relation) - - def on_any_relation(self, event): - assert event.relation.name == 'req1' - assert event.relation.app.name == 'remote' - self.seen.append(type(event).__name__) - - # language=YAML - self.meta = CharmMeta.from_yaml(metadata=''' -name: my-charm -requires: - req1: - interface: req1 - req-2: - interface: req2 -provides: - pro1: - interface: pro1 - pro-2: - interface: pro2 -peers: - peer1: - interface: peer1 - peer-2: - interface: peer2 -''') - - charm = MyCharm(self.create_framework(), None) - - rel = charm.framework.model.get_relation('req1', 1) - unit = charm.framework.model.get_unit('remote/0') - charm.on['req1'].relation_joined.emit(rel, unit) - charm.on['req1'].relation_changed.emit(rel, unit) - charm.on['req-2'].relation_changed.emit(rel, unit) - charm.on['pro1'].relation_departed.emit(rel, unit) - charm.on['pro-2'].relation_departed.emit(rel, unit) - charm.on['peer1'].relation_broken.emit(rel) - charm.on['peer-2'].relation_broken.emit(rel) - - self.assertEqual(charm.seen, [ - 'RelationJoinedEvent', - 'RelationChangedEvent', - 'RelationChangedEvent', - 'RelationDepartedEvent', - 'RelationDepartedEvent', - 'RelationBrokenEvent', - 'RelationBrokenEvent', - ]) - - def test_storage_events(self): - - class MyCharm(CharmBase): - def __init__(self, *args): - super().__init__(*args) - self.seen = [] - self.framework.observe(self.on['stor1'].storage_attached, self) - self.framework.observe(self.on['stor2'].storage_detaching, self) - self.framework.observe(self.on['stor3'].storage_attached, self) - self.framework.observe(self.on['stor-4'].storage_attached, self) - - def on_stor1_storage_attached(self, event): - self.seen.append(type(event).__name__) - - def on_stor2_storage_detaching(self, event): - self.seen.append(type(event).__name__) - - def on_stor3_storage_attached(self, event): - self.seen.append(type(event).__name__) - - def on_stor_4_storage_attached(self, event): - self.seen.append(type(event).__name__) - - # language=YAML - self.meta = CharmMeta.from_yaml(''' -name: my-charm -storage: - stor-4: - multiple: - range: 2-4 - type: filesystem - stor1: - type: filesystem - stor2: - multiple: - range: "2" - type: filesystem - stor3: - multiple: - range: 2- - type: filesystem -''') - - self.assertIsNone(self.meta.storages['stor1'].multiple_range) - self.assertEqual(self.meta.storages['stor2'].multiple_range, (2, 2)) - self.assertEqual(self.meta.storages['stor3'].multiple_range, (2, None)) - self.assertEqual(self.meta.storages['stor-4'].multiple_range, (2, 4)) - - charm = MyCharm(self.create_framework(), None) - - charm.on['stor1'].storage_attached.emit() - charm.on['stor2'].storage_detaching.emit() - charm.on['stor3'].storage_attached.emit() - charm.on['stor-4'].storage_attached.emit() - - self.assertEqual(charm.seen, [ - 'StorageAttachedEvent', - 'StorageDetachingEvent', - 'StorageAttachedEvent', - 'StorageAttachedEvent', - ]) - - @classmethod - def _get_action_test_meta(cls): - # language=YAML - return CharmMeta.from_yaml(metadata=''' -name: my-charm -''', actions=''' -foo-bar: - description: "Foos the bar." - params: - foo-name: - description: "A foo name to bar" - type: string - silent: - default: false - description: "" - type: boolean - required: foo-bar - title: foo-bar -start: - description: "Start the unit." -''') - - def _test_action_events(self, cmd_type): - - class MyCharm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - framework.observe(self.on.foo_bar_action, self) - framework.observe(self.on.start_action, self) - - def on_foo_bar_action(self, event): - self.seen_action_params = event.params - event.log('test-log') - event.set_results({'res': 'val with spaces'}) - event.fail('test-fail') - - def on_start_action(self, event): - pass - - fake_script(self, cmd_type + '-get', """echo '{"foo-name": "name", "silent": true}'""") - fake_script(self, cmd_type + '-set', "") - fake_script(self, cmd_type + '-log', "") - fake_script(self, cmd_type + '-fail', "") - self.meta = self._get_action_test_meta() - - os.environ['JUJU_{}_NAME'.format(cmd_type.upper())] = 'foo-bar' - framework = self.create_framework() - charm = MyCharm(framework, None) - - events = list(MyCharm.on.events()) - self.assertIn('foo_bar_action', events) - self.assertIn('start_action', events) - - charm.on.foo_bar_action.emit() - self.assertEqual(charm.seen_action_params, {"foo-name": "name", "silent": True}) - self.assertEqual(fake_script_calls(self), [ - [cmd_type + '-get', '--format=json'], - [cmd_type + '-log', "test-log"], - [cmd_type + '-set', "res=val with spaces"], - [cmd_type + '-fail', "test-fail"], - ]) - - # Make sure that action events that do not match the current context are - # not possible to emit by hand. - with self.assertRaises(RuntimeError): - charm.on.start_action.emit() - - def test_action_events(self): - self._test_action_events('action') - - def _test_action_event_defer_fails(self, cmd_type): - - class MyCharm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - framework.observe(self.on.start_action, self) - - def on_start_action(self, event): - event.defer() - - fake_script(self, cmd_type + '-get', """echo '{"foo-name": "name", "silent": true}'""") - self.meta = self._get_action_test_meta() - - os.environ['JUJU_{}_NAME'.format(cmd_type.upper())] = 'start' - framework = self.create_framework() - charm = MyCharm(framework, None) - - with self.assertRaises(RuntimeError): - charm.on.start_action.emit() - - def test_action_event_defer_fails(self): - self._test_action_event_defer_fails('action') - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py deleted file mode 100644 index 2ec4c4ed..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py +++ /dev/null @@ -1,1727 +0,0 @@ -# Copyright 2019-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. - -import datetime -import gc -import inspect -import io -import os -import shutil -import sys -import tempfile -import unittest -from unittest.mock import patch -from pathlib import Path - -from ops import charm, model -from ops.framework import ( - _BREAKPOINT_WELCOME_MESSAGE, - BoundStoredState, - CommitEvent, - EventBase, - ObjectEvents, - EventSource, - Framework, - Handle, - NoSnapshotError, - Object, - PreCommitEvent, - SQLiteStorage, - StoredList, - StoredState, - StoredStateData, -) -from test.test_helpers import fake_script - - -class TestFramework(unittest.TestCase): - - def setUp(self): - self.tmpdir = Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(self.tmpdir)) - default_timeout = SQLiteStorage.DB_LOCK_TIMEOUT - - def timeout_cleanup(): - SQLiteStorage.DB_LOCK_TIMEOUT = default_timeout - SQLiteStorage.DB_LOCK_TIMEOUT = datetime.timedelta(0) - self.addCleanup(timeout_cleanup) - - def create_framework(self): - framework = Framework(self.tmpdir / "framework.data", self.tmpdir, None, None) - self.addCleanup(framework.close) - return framework - - def test_handle_path(self): - cases = [ - (Handle(None, "root", None), "root"), - (Handle(None, "root", "1"), "root[1]"), - (Handle(Handle(None, "root", None), "child", None), "root/child"), - (Handle(Handle(None, "root", "1"), "child", "2"), "root[1]/child[2]"), - ] - for handle, path in cases: - self.assertEqual(str(handle), path) - self.assertEqual(Handle.from_path(path), handle) - - def test_handle_attrs_readonly(self): - handle = Handle(None, 'kind', 'key') - with self.assertRaises(AttributeError): - handle.parent = 'foo' - with self.assertRaises(AttributeError): - handle.kind = 'foo' - with self.assertRaises(AttributeError): - handle.key = 'foo' - with self.assertRaises(AttributeError): - handle.path = 'foo' - - def test_restore_unknown(self): - framework = self.create_framework() - - class Foo(Object): - pass - - handle = Handle(None, "a_foo", "some_key") - - framework.register_type(Foo, None, handle.kind) - - try: - framework.load_snapshot(handle) - except NoSnapshotError as e: - self.assertEqual(e.handle_path, str(handle)) - self.assertEqual(str(e), "no snapshot data found for a_foo[some_key] object") - else: - self.fail("exception NoSnapshotError not raised") - - def test_snapshot_roundtrip(self): - class Foo: - def __init__(self, handle, n): - self.handle = handle - self.my_n = n - - def snapshot(self): - return {"My N!": self.my_n} - - def restore(self, snapshot): - self.my_n = snapshot["My N!"] + 1 - - handle = Handle(None, "a_foo", "some_key") - event = Foo(handle, 1) - - framework1 = self.create_framework() - framework1.register_type(Foo, None, handle.kind) - framework1.save_snapshot(event) - framework1.commit() - framework1.close() - - framework2 = self.create_framework() - framework2.register_type(Foo, None, handle.kind) - event2 = framework2.load_snapshot(handle) - self.assertEqual(event2.my_n, 2) - - framework2.save_snapshot(event2) - del event2 - gc.collect() - event3 = framework2.load_snapshot(handle) - self.assertEqual(event3.my_n, 3) - - framework2.drop_snapshot(event.handle) - framework2.commit() - framework2.close() - - framework3 = self.create_framework() - framework3.register_type(Foo, None, handle.kind) - - self.assertRaises(NoSnapshotError, framework3.load_snapshot, handle) - - def test_simple_event_observer(self): - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyNotifier(Object): - foo = EventSource(MyEvent) - bar = EventSource(MyEvent) - baz = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_any(self, event): - self.seen.append("on_any:" + event.handle.kind) - - def on_foo(self, event): - self.seen.append("on_foo:" + event.handle.kind) - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - framework.observe(pub.foo, obs.on_any) - framework.observe(pub.bar, obs.on_any) - framework.observe(pub.foo, obs) # Method name defaults to on_. - - try: - framework.observe(pub.baz, obs) - except RuntimeError as e: - self.assertEqual( - str(e), - 'Observer method not provided explicitly' - ' and MyObserver type has no "on_baz" method') - else: - self.fail("RuntimeError not raised") - - pub.foo.emit() - pub.bar.emit() - - self.assertEqual(obs.seen, ["on_any:foo", "on_foo:foo", "on_any:bar"]) - - def test_bad_sig_observer(self): - - class MyEvent(EventBase): - pass - - class MyNotifier(Object): - foo = EventSource(MyEvent) - bar = EventSource(MyEvent) - baz = EventSource(MyEvent) - qux = EventSource(MyEvent) - - class MyObserver(Object): - def on_foo(self): - assert False, 'should not be reached' - - def on_bar(self, event, extra): - assert False, 'should not be reached' - - def on_baz(self, event, extra=None, *, k): - assert False, 'should not be reached' - - def on_qux(self, event, extra=None): - assert False, 'should not be reached' - - framework = self.create_framework() - pub = MyNotifier(framework, "pub") - obs = MyObserver(framework, "obs") - - with self.assertRaises(TypeError): - framework.observe(pub.foo, obs) - with self.assertRaises(TypeError): - framework.observe(pub.bar, obs) - with self.assertRaises(TypeError): - framework.observe(pub.baz, obs) - framework.observe(pub.qux, obs) - - def test_on_pre_commit_emitted(self): - framework = self.create_framework() - - class PreCommitObserver(Object): - - _stored = StoredState() - - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - self._stored.myinitdata = 40 - - def on_pre_commit(self, event): - self._stored.myinitdata = 41 - self._stored.mydata = 42 - self.seen.append(type(event)) - - def on_commit(self, event): - # Modifications made here will not be persisted. - self._stored.myinitdata = 42 - self._stored.mydata = 43 - self._stored.myotherdata = 43 - self.seen.append(type(event)) - - obs = PreCommitObserver(framework, None) - - framework.observe(framework.on.pre_commit, obs.on_pre_commit) - - framework.commit() - - self.assertEqual(obs._stored.myinitdata, 41) - self.assertEqual(obs._stored.mydata, 42) - self.assertTrue(obs.seen, [PreCommitEvent, CommitEvent]) - framework.close() - - other_framework = self.create_framework() - - new_obs = PreCommitObserver(other_framework, None) - - self.assertEqual(obs._stored.myinitdata, 41) - self.assertEqual(new_obs._stored.mydata, 42) - - with self.assertRaises(AttributeError): - new_obs._stored.myotherdata - - def test_defer_and_reemit(self): - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyNotifier1(Object): - a = EventSource(MyEvent) - b = EventSource(MyEvent) - - class MyNotifier2(Object): - c = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - self.done = {} - - def on_any(self, event): - self.seen.append(event.handle.kind) - if not self.done.get(event.handle.kind): - event.defer() - - pub1 = MyNotifier1(framework, "1") - pub2 = MyNotifier2(framework, "1") - obs1 = MyObserver(framework, "1") - obs2 = MyObserver(framework, "2") - - framework.observe(pub1.a, obs1.on_any) - framework.observe(pub1.b, obs1.on_any) - framework.observe(pub1.a, obs2.on_any) - framework.observe(pub1.b, obs2.on_any) - framework.observe(pub2.c, obs2.on_any) - - pub1.a.emit() - pub1.b.emit() - pub2.c.emit() - - # Events remain stored because they were deferred. - ev_a_handle = Handle(pub1, "a", "1") - framework.load_snapshot(ev_a_handle) - ev_b_handle = Handle(pub1, "b", "2") - framework.load_snapshot(ev_b_handle) - ev_c_handle = Handle(pub2, "c", "3") - framework.load_snapshot(ev_c_handle) - # make sure the objects are gone before we reemit them - gc.collect() - - framework.reemit() - obs1.done["a"] = True - obs2.done["b"] = True - framework.reemit() - framework.reemit() - obs1.done["b"] = True - obs2.done["a"] = True - framework.reemit() - obs2.done["c"] = True - framework.reemit() - framework.reemit() - framework.reemit() - - self.assertEqual(" ".join(obs1.seen), "a b a b a b b b") - self.assertEqual(" ".join(obs2.seen), "a b c a b c a b c a c a c c") - - # Now the event objects must all be gone from storage. - self.assertRaises(NoSnapshotError, framework.load_snapshot, ev_a_handle) - self.assertRaises(NoSnapshotError, framework.load_snapshot, ev_b_handle) - self.assertRaises(NoSnapshotError, framework.load_snapshot, ev_c_handle) - - def test_custom_event_data(self): - framework = self.create_framework() - - class MyEvent(EventBase): - def __init__(self, handle, n): - super().__init__(handle) - self.my_n = n - - def snapshot(self): - return {"My N!": self.my_n} - - def restore(self, snapshot): - super().restore(snapshot) - self.my_n = snapshot["My N!"] + 1 - - class MyNotifier(Object): - foo = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}={}".format(event.handle.kind, event.my_n)) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - framework.observe(pub.foo, obs) - - pub.foo.emit(1) - - framework.reemit() - - # Two things being checked here: - # - # 1. There's a restore roundtrip before the event is first observed. - # That means the data is safe before it's ever seen, and the - # roundtrip logic is tested under normal circumstances. - # - # 2. The renotification restores from the pristine event, not - # from the one modified during the first restore (otherwise - # we'd get a foo=3). - # - self.assertEqual(obs.seen, ["on_foo:foo=2", "on_foo:foo=2"]) - - def test_weak_observer(self): - framework = self.create_framework() - - observed_events = [] - - class MyEvent(EventBase): - pass - - class MyEvents(ObjectEvents): - foo = EventSource(MyEvent) - - class MyNotifier(Object): - on = MyEvents() - - class MyObserver(Object): - def on_foo(self, event): - observed_events.append("foo") - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "2") - - framework.observe(pub.on.foo, obs) - pub.on.foo.emit() - self.assertEqual(observed_events, ["foo"]) - # Now delete the observer, and note that when we emit the event, it - # doesn't update the local slice again - del obs - gc.collect() - pub.on.foo.emit() - self.assertEqual(observed_events, ["foo"]) - - def test_forget_and_multiple_objects(self): - framework = self.create_framework() - - class MyObject(Object): - pass - - o1 = MyObject(framework, "path") - # Creating a second object at the same path should fail with RuntimeError - with self.assertRaises(RuntimeError): - o2 = MyObject(framework, "path") - # Unless we _forget the object first - framework._forget(o1) - o2 = MyObject(framework, "path") - self.assertEqual(o1.handle.path, o2.handle.path) - # Deleting the tracked object should also work - del o2 - gc.collect() - o3 = MyObject(framework, "path") - self.assertEqual(o1.handle.path, o3.handle.path) - framework.close() - # Or using a second framework - framework_copy = self.create_framework() - o_copy = MyObject(framework_copy, "path") - self.assertEqual(o1.handle.path, o_copy.handle.path) - - def test_forget_and_multiple_objects_with_load_snapshot(self): - framework = self.create_framework() - - class MyObject(Object): - def __init__(self, parent, name): - super().__init__(parent, name) - self.value = name - - def snapshot(self): - return self.value - - def restore(self, value): - self.value = value - - framework.register_type(MyObject, None, MyObject.handle_kind) - o1 = MyObject(framework, "path") - framework.save_snapshot(o1) - framework.commit() - o_handle = o1.handle - del o1 - gc.collect() - o2 = framework.load_snapshot(o_handle) - # Trying to load_snapshot a second object at the same path should fail with RuntimeError - with self.assertRaises(RuntimeError): - framework.load_snapshot(o_handle) - # Unless we _forget the object first - framework._forget(o2) - o3 = framework.load_snapshot(o_handle) - self.assertEqual(o2.value, o3.value) - # A loaded object also prevents direct creation of an object - with self.assertRaises(RuntimeError): - MyObject(framework, "path") - framework.close() - # But we can create an object, or load a snapshot in a copy of the framework - framework_copy1 = self.create_framework() - o_copy1 = MyObject(framework_copy1, "path") - self.assertEqual(o_copy1.value, "path") - framework_copy1.close() - framework_copy2 = self.create_framework() - framework_copy2.register_type(MyObject, None, MyObject.handle_kind) - o_copy2 = framework_copy2.load_snapshot(o_handle) - self.assertEqual(o_copy2.value, "path") - - def test_events_base(self): - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyEvents(ObjectEvents): - foo = EventSource(MyEvent) - bar = EventSource(MyEvent) - - class MyNotifier(Object): - on = MyEvents() - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}".format(event.handle.kind)) - event.defer() - - def on_bar(self, event): - self.seen.append("on_bar:{}".format(event.handle.kind)) - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - # Confirm that temporary persistence of BoundEvents doesn't cause errors, - # and that events can be observed. - for bound_event in [pub.on.foo, pub.on.bar]: - framework.observe(bound_event, obs) - - # Confirm that events can be emitted and seen. - pub.on.foo.emit() - - self.assertEqual(obs.seen, ["on_foo:foo"]) - - def test_conflicting_event_attributes(self): - class MyEvent(EventBase): - pass - - event = EventSource(MyEvent) - - class MyEvents(ObjectEvents): - foo = event - - with self.assertRaises(RuntimeError) as cm: - class OtherEvents(ObjectEvents): - foo = event - self.assertEqual( - str(cm.exception), - "EventSource(MyEvent) reused as MyEvents.foo and OtherEvents.foo") - - with self.assertRaises(RuntimeError) as cm: - class MyNotifier(Object): - on = MyEvents() - bar = event - self.assertEqual( - str(cm.exception), - "EventSource(MyEvent) reused as MyEvents.foo and MyNotifier.bar") - - def test_reemit_ignores_unknown_event_type(self): - # The event type may have been gone for good, and nobody cares, - # so this shouldn't be an error scenario. - - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyNotifier(Object): - foo = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append(event.handle) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - framework.observe(pub.foo, obs) - pub.foo.emit() - - event_handle = obs.seen[0] - self.assertEqual(event_handle.kind, "foo") - - framework.commit() - framework.close() - - framework_copy = self.create_framework() - - # No errors on missing event types here. - framework_copy.reemit() - - # Register the type and check that the event is gone from storage. - framework_copy.register_type(MyEvent, event_handle.parent, event_handle.kind) - self.assertRaises(NoSnapshotError, framework_copy.load_snapshot, event_handle) - - def test_auto_register_event_types(self): - framework = self.create_framework() - - class MyFoo(EventBase): - pass - - class MyBar(EventBase): - pass - - class MyEvents(ObjectEvents): - foo = EventSource(MyFoo) - - class MyNotifier(Object): - on = MyEvents() - bar = EventSource(MyBar) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - def on_bar(self, event): - self.seen.append("on_bar:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - pub.on.foo.emit() - pub.bar.emit() - - framework.observe(pub.on.foo, obs) - framework.observe(pub.bar, obs) - - pub.on.foo.emit() - pub.bar.emit() - - self.assertEqual(obs.seen, ["on_foo:MyFoo:foo", "on_bar:MyBar:bar"]) - - def test_dynamic_event_types(self): - framework = self.create_framework() - - class MyEventsA(ObjectEvents): - handle_kind = 'on_a' - - class MyEventsB(ObjectEvents): - handle_kind = 'on_b' - - class MyNotifier(Object): - on_a = MyEventsA() - on_b = MyEventsB() - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - def on_bar(self, event): - self.seen.append("on_bar:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - class MyFoo(EventBase): - pass - - class MyBar(EventBase): - pass - - class DeadBeefEvent(EventBase): - pass - - class NoneEvent(EventBase): - pass - - pub.on_a.define_event("foo", MyFoo) - pub.on_b.define_event("bar", MyBar) - - framework.observe(pub.on_a.foo, obs) - framework.observe(pub.on_b.bar, obs) - - pub.on_a.foo.emit() - pub.on_b.bar.emit() - - self.assertEqual(obs.seen, ["on_foo:MyFoo:foo", "on_bar:MyBar:bar"]) - - # Definitions remained local to the specific type. - self.assertRaises(AttributeError, lambda: pub.on_a.bar) - self.assertRaises(AttributeError, lambda: pub.on_b.foo) - - # Try to use an event name which is not a valid python identifier. - with self.assertRaises(RuntimeError): - pub.on_a.define_event("dead-beef", DeadBeefEvent) - - # Try to use a python keyword for an event name. - with self.assertRaises(RuntimeError): - pub.on_a.define_event("None", NoneEvent) - - # Try to override an existing attribute. - with self.assertRaises(RuntimeError): - pub.on_a.define_event("foo", MyFoo) - - def test_event_key_roundtrip(self): - class MyEvent(EventBase): - def __init__(self, handle, value): - super().__init__(handle) - self.value = value - - def snapshot(self): - return self.value - - def restore(self, value): - self.value = value - - class MyNotifier(Object): - foo = EventSource(MyEvent) - - class MyObserver(Object): - has_deferred = False - - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append((event.handle.key, event.value)) - # Only defer the first event and once. - if not MyObserver.has_deferred: - event.defer() - MyObserver.has_deferred = True - - framework1 = self.create_framework() - pub1 = MyNotifier(framework1, "pub") - obs1 = MyObserver(framework1, "obs") - framework1.observe(pub1.foo, obs1) - pub1.foo.emit('first') - self.assertEqual(obs1.seen, [('1', 'first')]) - - framework1.commit() - framework1.close() - del framework1 - - framework2 = self.create_framework() - pub2 = MyNotifier(framework2, "pub") - obs2 = MyObserver(framework2, "obs") - framework2.observe(pub2.foo, obs2) - pub2.foo.emit('second') - framework2.reemit() - - # First observer didn't get updated, since framework it was bound to is gone. - self.assertEqual(obs1.seen, [('1', 'first')]) - # Second observer saw the new event plus the reemit of the first event. - # (The event key goes up by 2 due to the pre-commit and commit events.) - self.assertEqual(obs2.seen, [('4', 'second'), ('1', 'first')]) - - def test_helper_properties(self): - framework = self.create_framework() - framework.model = 'test-model' - framework.meta = 'test-meta' - - my_obj = Object(framework, 'my_obj') - self.assertEqual(my_obj.model, framework.model) - - def test_ban_concurrent_frameworks(self): - f = self.create_framework() - with self.assertRaises(Exception) as cm: - self.create_framework() - self.assertIn('database is locked', str(cm.exception)) - f.close() - - def test_snapshot_saving_restricted_to_simple_types(self): - # this can not be saved, as it has not simple types! - to_be_saved = {"bar": TestFramework} - - class FooEvent(EventBase): - def snapshot(self): - return to_be_saved - - handle = Handle(None, "a_foo", "some_key") - event = FooEvent(handle) - - framework = self.create_framework() - framework.register_type(FooEvent, None, handle.kind) - with self.assertRaises(ValueError) as cm: - framework.save_snapshot(event) - expected = ( - "unable to save the data for FooEvent, it must contain only simple types: " - "{'bar': }") - self.assertEqual(str(cm.exception), expected) - - -class TestStoredState(unittest.TestCase): - - def setUp(self): - self.tmpdir = Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(self.tmpdir)) - - def create_framework(self, cls=Framework): - framework = cls(self.tmpdir / "framework.data", self.tmpdir, None, None) - self.addCleanup(framework.close) - return framework - - def test_basic_state_storage(self): - class SomeObject(Object): - _stored = StoredState() - - self._stored_state_tests(SomeObject) - - def test_straight_subclass(self): - class SomeObject(Object): - _stored = StoredState() - - class Sub(SomeObject): - pass - - self._stored_state_tests(Sub) - - def test_straight_sub_subclass(self): - class SomeObject(Object): - _stored = StoredState() - - class Sub(SomeObject): - pass - - class SubSub(SomeObject): - pass - - self._stored_state_tests(SubSub) - - def test_two_subclasses(self): - class SomeObject(Object): - _stored = StoredState() - - class SubA(SomeObject): - pass - - class SubB(SomeObject): - pass - - self._stored_state_tests(SubA) - self._stored_state_tests(SubB) - - def test_the_crazy_thing(self): - class NoState(Object): - pass - - class StatedObject(NoState): - _stored = StoredState() - - class Sibling(NoState): - pass - - class FinalChild(StatedObject, Sibling): - pass - - self._stored_state_tests(FinalChild) - - def _stored_state_tests(self, cls): - framework = self.create_framework() - obj = cls(framework, "1") - - try: - obj._stored.foo - except AttributeError as e: - self.assertEqual(str(e), "attribute 'foo' is not stored") - else: - self.fail("AttributeError not raised") - - try: - obj._stored.on = "nonono" - except AttributeError as e: - self.assertEqual(str(e), "attribute 'on' is reserved and cannot be set") - else: - self.fail("AttributeError not raised") - - obj._stored.foo = 41 - obj._stored.foo = 42 - obj._stored.bar = "s" - obj._stored.baz = 4.2 - obj._stored.bing = True - - self.assertEqual(obj._stored.foo, 42) - - framework.commit() - - # This won't be committed, and should not be seen. - obj._stored.foo = 43 - - framework.close() - - # Since this has the same absolute object handle, it will get its state back. - framework_copy = self.create_framework() - obj_copy = cls(framework_copy, "1") - self.assertEqual(obj_copy._stored.foo, 42) - self.assertEqual(obj_copy._stored.bar, "s") - self.assertEqual(obj_copy._stored.baz, 4.2) - self.assertEqual(obj_copy._stored.bing, True) - - framework_copy.close() - - def test_two_subclasses_no_conflicts(self): - class Base(Object): - _stored = StoredState() - - class SubA(Base): - pass - - class SubB(Base): - pass - - framework = self.create_framework() - a = SubA(framework, None) - b = SubB(framework, None) - z = Base(framework, None) - - a._stored.foo = 42 - b._stored.foo = "hello" - z._stored.foo = {1} - - framework.commit() - framework.close() - - framework2 = self.create_framework() - a2 = SubA(framework2, None) - b2 = SubB(framework2, None) - z2 = Base(framework2, None) - - self.assertEqual(a2._stored.foo, 42) - self.assertEqual(b2._stored.foo, "hello") - self.assertEqual(z2._stored.foo, {1}) - - def test_two_names_one_state(self): - class Mine(Object): - _stored = StoredState() - _stored2 = _stored - - framework = self.create_framework() - obj = Mine(framework, None) - - with self.assertRaises(RuntimeError): - obj._stored.foo = 42 - - with self.assertRaises(RuntimeError): - obj._stored2.foo = 42 - - framework.close() - - # make sure we're not changing the object on failure - self.assertNotIn("_stored", obj.__dict__) - self.assertNotIn("_stored2", obj.__dict__) - - def test_same_name_two_classes(self): - class Base(Object): - pass - - class A(Base): - _stored = StoredState() - - class B(Base): - _stored = A._stored - - framework = self.create_framework() - a = A(framework, None) - b = B(framework, None) - - # NOTE it's the second one that actually triggers the - # exception, but that's an implementation detail - a._stored.foo = 42 - - with self.assertRaises(RuntimeError): - b._stored.foo = "xyzzy" - - framework.close() - - # make sure we're not changing the object on failure - self.assertNotIn("_stored", b.__dict__) - - def test_mutable_types_invalid(self): - framework = self.create_framework() - - class SomeObject(Object): - _stored = StoredState() - - obj = SomeObject(framework, '1') - try: - class CustomObject: - pass - obj._stored.foo = CustomObject() - except AttributeError as e: - self.assertEqual( - str(e), - "attribute 'foo' cannot be a CustomObject: must be int/float/dict/list/etc") - else: - self.fail('AttributeError not raised') - - framework.commit() - - def test_mutable_types(self): - # Test and validation functions in a list of 2-tuples. - # Assignment and keywords like del are not supported in lambdas - # so functions are used instead. - test_operations = [( - lambda: {}, # Operand A. - None, # Operand B. - {}, # Expected result. - lambda a, b: None, # Operation to perform. - lambda res, expected_res: self.assertEqual(res, expected_res) # Validation to perform. - ), ( - lambda: {}, - {'a': {}}, - {'a': {}}, - lambda a, b: a.update(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'a': {}}, - {'b': 'c'}, - {'a': {'b': 'c'}}, - lambda a, b: a['a'].update(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'a': {'b': 'c'}}, - {'d': 'e'}, - {'a': {'b': 'c', 'd': 'e'}}, - lambda a, b: a['a'].update(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'a': {'b': 'c', 'd': 'e'}}, - 'd', - {'a': {'b': 'c'}}, - lambda a, b: a['a'].pop(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'s': set()}, - 'a', - {'s': {'a'}}, - lambda a, b: a['s'].add(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'s': {'a'}}, - 'a', - {'s': set()}, - lambda a, b: a['s'].discard(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: [], - None, - [], - lambda a, b: None, - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: [], - 'a', - ['a'], - lambda a, b: a.append(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a'], - ['c'], - ['a', ['c']], - lambda a, b: a.append(b), - lambda res, expected_res: ( - self.assertEqual(res, expected_res), - self.assertIsInstance(res[1], StoredList), - ) - ), ( - lambda: ['a', ['c']], - 'b', - ['b', 'a', ['c']], - lambda a, b: a.insert(0, b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['b', 'a', ['c']], - ['d'], - ['b', ['d'], 'a', ['c']], - lambda a, b: a.insert(1, b), - lambda res, expected_res: ( - self.assertEqual(res, expected_res), - self.assertIsInstance(res[1], StoredList) - ), - ), ( - lambda: ['b', 'a', ['c']], - ['d'], - ['b', ['d'], ['c']], - # a[1] = b - lambda a, b: a.__setitem__(1, b), - lambda res, expected_res: ( - self.assertEqual(res, expected_res), - self.assertIsInstance(res[1], StoredList) - ), - ), ( - lambda: ['b', ['d'], 'a', ['c']], - 0, - [['d'], 'a', ['c']], - lambda a, b: a.pop(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: [['d'], 'a', ['c']], - ['d'], - ['a', ['c']], - lambda a, b: a.remove(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c']], - 'd', - ['a', ['c', 'd']], - lambda a, b: a[1].append(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c', 'd']], - 1, - ['a', ['c']], - lambda a, b: a[1].pop(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c']], - 'd', - ['a', ['c', 'd']], - lambda a, b: a[1].insert(1, b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c', 'd']], - 'd', - ['a', ['c']], - lambda a, b: a[1].remove(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(), - None, - set(), - lambda a, b: None, - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(), - 'a', - set(['a']), - lambda a, b: a.add(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(['a']), - 'a', - set(), - lambda a, b: a.discard(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(), - {'a'}, - set(), - # Nested sets are not allowed as sets themselves are not hashable. - lambda a, b: self.assertRaises(TypeError, a.add, b), - lambda res, expected_res: self.assertEqual(res, expected_res) - )] - - class SomeObject(Object): - _stored = StoredState() - - class WrappedFramework(Framework): - def __init__(self, data_path, charm_dir, meta, model): - super().__init__(data_path, charm_dir, meta, model) - self.snapshots = [] - - def save_snapshot(self, value): - if value.handle.path == 'SomeObject[1]/StoredStateData[_stored]': - self.snapshots.append((type(value), value.snapshot())) - return super().save_snapshot(value) - - # Validate correctness of modification operations. - for get_a, b, expected_res, op, validate_op in test_operations: - framework = self.create_framework(cls=WrappedFramework) - obj = SomeObject(framework, '1') - - obj._stored.a = get_a() - self.assertTrue(isinstance(obj._stored, BoundStoredState)) - - op(obj._stored.a, b) - validate_op(obj._stored.a, expected_res) - - obj._stored.a = get_a() - framework.commit() - # We should see an update for initializing a - self.assertEqual(framework.snapshots, [ - (StoredStateData, {'a': get_a()}), - ]) - del obj - gc.collect() - obj_copy1 = SomeObject(framework, '1') - self.assertEqual(obj_copy1._stored.a, get_a()) - - op(obj_copy1._stored.a, b) - validate_op(obj_copy1._stored.a, expected_res) - framework.commit() - framework.close() - - framework_copy = self.create_framework(cls=WrappedFramework) - - obj_copy2 = SomeObject(framework_copy, '1') - - validate_op(obj_copy2._stored.a, expected_res) - - # Commit saves the pre-commit and commit events, and the framework - # event counter, but shouldn't update the stored state of my object - framework.snapshots.clear() - framework_copy.commit() - self.assertEqual(framework_copy.snapshots, []) - framework_copy.close() - - def test_comparison_operations(self): - test_operations = [( - {"1"}, # Operand A. - {"1", "2"}, # Operand B. - lambda a, b: a < b, # Operation to test. - True, # Result of op(A, B). - False, # Result of op(B, A). - ), ( - {"1"}, - {"1", "2"}, - lambda a, b: a > b, - False, - True - ), ( - # Empty set comparison. - set(), - set(), - lambda a, b: a == b, - True, - True - ), ( - {"a", "c"}, - {"c", "a"}, - lambda a, b: a == b, - True, - True - ), ( - dict(), - dict(), - lambda a, b: a == b, - True, - True - ), ( - {"1": "2"}, - {"1": "2"}, - lambda a, b: a == b, - True, - True - ), ( - {"1": "2"}, - {"1": "3"}, - lambda a, b: a == b, - False, - False - ), ( - [], - [], - lambda a, b: a == b, - True, - True - ), ( - [1, 2], - [1, 2], - lambda a, b: a == b, - True, - True - ), ( - [1, 2, 5, 6], - [1, 2, 5, 8, 10], - lambda a, b: a <= b, - True, - False - ), ( - [1, 2, 5, 6], - [1, 2, 5, 8, 10], - lambda a, b: a < b, - True, - False - ), ( - [1, 2, 5, 8], - [1, 2, 5, 6, 10], - lambda a, b: a > b, - True, - False - ), ( - [1, 2, 5, 8], - [1, 2, 5, 6, 10], - lambda a, b: a >= b, - True, - False - )] - - class SomeObject(Object): - _stored = StoredState() - - framework = self.create_framework() - - for i, (a, b, op, op_ab, op_ba) in enumerate(test_operations): - obj = SomeObject(framework, str(i)) - obj._stored.a = a - self.assertEqual(op(obj._stored.a, b), op_ab) - self.assertEqual(op(b, obj._stored.a), op_ba) - - def test_set_operations(self): - test_operations = [( - {"1"}, # A set to test an operation against (other_set). - lambda a, b: a | b, # An operation to test. - {"1", "a", "b"}, # The expected result of operation(obj._stored.set, other_set). - {"1", "a", "b"} # The expected result of operation(other_set, obj._stored.set). - ), ( - {"a", "c"}, - lambda a, b: a - b, - {"b"}, - {"c"} - ), ( - {"a", "c"}, - lambda a, b: a & b, - {"a"}, - {"a"} - ), ( - {"a", "c", "d"}, - lambda a, b: a ^ b, - {"b", "c", "d"}, - {"b", "c", "d"} - ), ( - set(), - lambda a, b: set(a), - {"a", "b"}, - set() - )] - - class SomeObject(Object): - _stored = StoredState() - - framework = self.create_framework() - - # Validate that operations between StoredSet and built-in sets - # only result in built-in sets being returned. - # Make sure that commutativity is preserved and that the - # original sets are not changed or used as a result. - for i, (variable_operand, operation, ab_res, ba_res) in enumerate(test_operations): - obj = SomeObject(framework, str(i)) - obj._stored.set = {"a", "b"} - - for a, b, expected in [ - (obj._stored.set, variable_operand, ab_res), - (variable_operand, obj._stored.set, ba_res)]: - old_a = set(a) - old_b = set(b) - - result = operation(a, b) - self.assertEqual(result, expected) - - # Common sanity checks - self.assertIsNot(obj._stored.set._under, result) - self.assertIsNot(result, a) - self.assertIsNot(result, b) - self.assertEqual(a, old_a) - self.assertEqual(b, old_b) - - def test_set_default(self): - framework = self.create_framework() - - class StatefulObject(Object): - _stored = StoredState() - parent = StatefulObject(framework, 'key') - parent._stored.set_default(foo=1) - self.assertEqual(parent._stored.foo, 1) - parent._stored.set_default(foo=2) - # foo was already set, so it doesn't get replaced - self.assertEqual(parent._stored.foo, 1) - parent._stored.set_default(foo=3, bar=4) - self.assertEqual(parent._stored.foo, 1) - self.assertEqual(parent._stored.bar, 4) - # reloading the state still leaves things at the default values - framework.commit() - del parent - parent = StatefulObject(framework, 'key') - parent._stored.set_default(foo=5, bar=6) - self.assertEqual(parent._stored.foo, 1) - self.assertEqual(parent._stored.bar, 4) - # TODO: jam 2020-01-30 is there a clean way to tell that - # parent._stored._data.dirty is False? - - -def create_model(testcase): - """Create a Model object.""" - unit_name = 'myapp/0' - patcher = patch.dict(os.environ, {'JUJU_UNIT_NAME': unit_name}) - patcher.start() - testcase.addCleanup(patcher.stop) - - backend = model.ModelBackend() - meta = charm.CharmMeta() - test_model = model.Model('myapp/0', meta, backend) - return test_model - - -def create_framework(testcase, model=None): - """Create a Framework object.""" - framework = Framework(":memory:", charm_dir='non-existant', meta=None, model=model) - testcase.addCleanup(framework.close) - return framework - - -class GenericObserver(Object): - """Generic observer for the tests.""" - - def __init__(self, parent, key): - super().__init__(parent, key) - self.called = False - - def callback_method(self, event): - """Set the instance .called to True.""" - self.called = True - - -@patch('sys.stderr', new_callable=io.StringIO) -class BreakpointTests(unittest.TestCase): - - def test_ignored(self, fake_stderr): - # It doesn't do anything really unless proper environment is there. - with patch.dict(os.environ): - os.environ.pop('JUJU_DEBUG_AT', None) - framework = create_framework(self) - - with patch('pdb.Pdb.set_trace') as mock: - framework.breakpoint() - self.assertEqual(mock.call_count, 0) - self.assertEqual(fake_stderr.getvalue(), "") - - def test_pdb_properly_called(self, fake_stderr): - # The debugger needs to leave the user in the frame where the breakpoint is executed, - # which for the test is the frame we're calling it here in the test :). - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - framework = create_framework(self) - - with patch('pdb.Pdb.set_trace') as mock: - this_frame = inspect.currentframe() - framework.breakpoint() - - self.assertEqual(mock.call_count, 1) - self.assertEqual(mock.call_args, ((this_frame,), {})) - - def test_welcome_message(self, fake_stderr): - # Check that an initial message is shown to the user when code is interrupted. - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - framework = create_framework(self) - with patch('pdb.Pdb.set_trace'): - framework.breakpoint() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - - def test_welcome_message_not_multiple(self, fake_stderr): - # Check that an initial message is NOT shown twice if the breakpoint is exercised - # twice in the same run. - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - framework = create_framework(self) - with patch('pdb.Pdb.set_trace'): - framework.breakpoint() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - framework.breakpoint() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - - def test_builtin_breakpoint_hooked(self, fake_stderr): - # Verify that the proper hook is set. - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - create_framework(self) # creating the framework setups the hook - with patch('pdb.Pdb.set_trace') as mock: - # Calling through sys, not breakpoint() directly, so we can run the - # tests with Py < 3.7. - sys.breakpointhook() - self.assertEqual(mock.call_count, 1) - - def test_breakpoint_names(self, fake_stderr): - framework = create_framework(self) - - # Name rules: - # - must start and end with lowercase alphanumeric characters - # - only contain lowercase alphanumeric characters, or the hyphen "-" - good_names = [ - 'foobar', - 'foo-bar-baz', - 'foo-------bar', - 'foo123', - '778', - '77-xx', - 'a-b', - 'ab', - 'x', - ] - for name in good_names: - with self.subTest(name=name): - framework.breakpoint(name) - - bad_names = [ - '', - '.', - '-', - '...foo', - 'foo.bar', - 'bar--' - 'FOO', - 'FooBar', - 'foo bar', - 'foo_bar', - '/foobar', - 'break-here-☚', - ] - msg = 'breakpoint names must look like "foo" or "foo-bar"' - for name in bad_names: - with self.subTest(name=name): - with self.assertRaises(ValueError) as cm: - framework.breakpoint(name) - self.assertEqual(str(cm.exception), msg) - - reserved_names = [ - 'all', - 'hook', - ] - msg = 'breakpoint names "all" and "hook" are reserved' - for name in reserved_names: - with self.subTest(name=name): - with self.assertRaises(ValueError) as cm: - framework.breakpoint(name) - self.assertEqual(str(cm.exception), msg) - - not_really_names = [ - 123, - 1.1, - False, - ] - for name in not_really_names: - with self.subTest(name=name): - with self.assertRaises(TypeError) as cm: - framework.breakpoint(name) - self.assertEqual(str(cm.exception), 'breakpoint names must be strings') - - def check_trace_set(self, envvar_value, breakpoint_name, call_count): - """Helper to check the diverse combinations of situations.""" - with patch.dict(os.environ, {'JUJU_DEBUG_AT': envvar_value}): - framework = create_framework(self) - with patch('pdb.Pdb.set_trace') as mock: - framework.breakpoint(breakpoint_name) - self.assertEqual(mock.call_count, call_count) - - def test_unnamed_indicated_all(self, fake_stderr): - # If 'all' is indicated, unnamed breakpoints will always activate. - self.check_trace_set('all', None, 1) - - def test_unnamed_indicated_hook(self, fake_stderr): - # Special value 'hook' was indicated, nothing to do with any call. - self.check_trace_set('hook', None, 0) - - def test_named_indicated_specifically(self, fake_stderr): - # Some breakpoint was indicated, and the framework call used exactly that name. - self.check_trace_set('mybreak', 'mybreak', 1) - - def test_named_indicated_somethingelse(self, fake_stderr): - # Some breakpoint was indicated, but the framework call was not with that name. - self.check_trace_set('some-breakpoint', None, 0) - - def test_named_indicated_ingroup(self, fake_stderr): - # A multiple breakpoint was indicated, and the framework call used a name among those. - self.check_trace_set('some,mybreak,foobar', 'mybreak', 1) - - def test_named_indicated_all(self, fake_stderr): - # The framework indicated 'all', which includes any named breakpoint set. - self.check_trace_set('all', 'mybreak', 1) - - def test_named_indicated_hook(self, fake_stderr): - # The framework indicated the special value 'hook', nothing to do with any named call. - self.check_trace_set('hook', 'mybreak', 0) - - -class DebugHookTests(unittest.TestCase): - - def test_envvar_parsing_missing(self): - with patch.dict(os.environ): - os.environ.pop('JUJU_DEBUG_AT', None) - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ()) - - def test_envvar_parsing_empty(self): - with patch.dict(os.environ, {'JUJU_DEBUG_AT': ''}): - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ()) - - def test_envvar_parsing_simple(self): - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'hook'}): - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ['hook']) - - def test_envvar_parsing_multiple(self): - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'foo,bar,all'}): - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ['foo', 'bar', 'all']) - - def test_basic_interruption_enabled(self): - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('sys.stderr', new_callable=io.StringIO) as fake_stderr: - with patch('pdb.runcall') as mock: - publisher.install.emit() - - # Check that the pdb module was used correctly and that the callback method was NOT - # called (as we intercepted the normal pdb behaviour! this is to check that the - # framework didn't call the callback directly) - self.assertEqual(mock.call_count, 1) - expected_callback, expected_event = mock.call_args[0] - self.assertEqual(expected_callback, observer.callback_method) - self.assertIsInstance(expected_event, EventBase) - self.assertFalse(observer.called) - - # Verify proper message was given to the user. - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - - def test_actions_are_interrupted(self): - test_model = create_model(self) - framework = create_framework(self, model=test_model) - framework._juju_debug_at = ['hook'] - - class CustomEvents(ObjectEvents): - foobar_action = EventSource(charm.ActionEvent) - - publisher = CustomEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.foobar_action, observer.callback_method) - fake_script(self, 'action-get', "echo {}") - - with patch('sys.stderr', new_callable=io.StringIO): - with patch('pdb.runcall') as mock: - with patch.dict(os.environ, {'JUJU_ACTION_NAME': 'foobar'}): - publisher.foobar_action.emit() - - self.assertEqual(mock.call_count, 1) - self.assertFalse(observer.called) - - def test_internal_events_not_interrupted(self): - class MyNotifier(Object): - """Generic notifier for the tests.""" - bar = EventSource(EventBase) - - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = MyNotifier(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.bar, observer.callback_method) - - with patch('pdb.runcall') as mock: - publisher.bar.emit() - - self.assertEqual(mock.call_count, 0) - self.assertTrue(observer.called) - - def test_envvar_mixed(self): - framework = create_framework(self) - framework._juju_debug_at = ['foo', 'hook', 'all', 'whatever'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('sys.stderr', new_callable=io.StringIO): - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 1) - self.assertFalse(observer.called) - - def test_no_registered_method(self): - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 0) - self.assertFalse(observer.called) - - def test_envvar_nohook(self): - framework = create_framework(self) - framework._juju_debug_at = ['something-else'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'something-else'}): - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 0) - self.assertTrue(observer.called) - - def test_envvar_missing(self): - framework = create_framework(self) - framework._juju_debug_at = () - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 0) - self.assertTrue(observer.called) - - def test_welcome_message_not_multiple(self): - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('sys.stderr', new_callable=io.StringIO) as fake_stderr: - with patch('pdb.runcall') as mock: - publisher.install.emit() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - publisher.install.emit() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - self.assertEqual(mock.call_count, 2) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py deleted file mode 100644 index 131681d0..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2019 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. - -import os -import pathlib -import subprocess -import shutil -import tempfile -import unittest - - -def fake_script(test_case, name, content): - if not hasattr(test_case, 'fake_script_path'): - fake_script_path = tempfile.mkdtemp('-fake_script') - os.environ['PATH'] = '{}:{}'.format(fake_script_path, os.environ["PATH"]) - - def cleanup(): - shutil.rmtree(fake_script_path) - os.environ['PATH'] = os.environ['PATH'].replace(fake_script_path + ':', '') - - test_case.addCleanup(cleanup) - test_case.fake_script_path = pathlib.Path(fake_script_path) - - with (test_case.fake_script_path / name).open('wt') as f: - # Before executing the provided script, dump the provided arguments in calls.txt. - f.write('''#!/bin/bash -{ echo -n $(basename $0); printf ";%s" "$@"; echo; } >> $(dirname $0)/calls.txt -''' + content) - os.chmod(str(test_case.fake_script_path / name), 0o755) - - -def fake_script_calls(test_case, clear=False): - try: - with (test_case.fake_script_path / 'calls.txt').open('r+t') as f: - calls = [line.split(';') for line in f.read().splitlines()] - if clear: - f.truncate(0) - return calls - except FileNotFoundError: - return [] - - -class FakeScriptTest(unittest.TestCase): - - def test_fake_script_works(self): - fake_script(self, 'foo', 'echo foo runs') - fake_script(self, 'bar', 'echo bar runs') - output = subprocess.getoutput('foo a "b c "; bar "d e" f') - self.assertEqual(output, 'foo runs\nbar runs') - self.assertEqual(fake_script_calls(self), [ - ['foo', 'a', 'b c '], - ['bar', 'd e', 'f'], - ]) - - def test_fake_script_clear(self): - fake_script(self, 'foo', 'echo foo runs') - - output = subprocess.getoutput('foo a "b c"') - self.assertEqual(output, 'foo runs') - - self.assertEqual(fake_script_calls(self, clear=True), [['foo', 'a', 'b c']]) - - fake_script(self, 'bar', 'echo bar runs') - - output = subprocess.getoutput('bar "d e" f') - self.assertEqual(output, 'bar runs') - - self.assertEqual(fake_script_calls(self, clear=True), [['bar', 'd e', 'f']]) - - self.assertEqual(fake_script_calls(self, clear=True), []) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py deleted file mode 100644 index 9d269547..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py +++ /dev/null @@ -1,130 +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. - -import io -import itertools -import os -import re -import subprocess -import sys -import tempfile -import unittest -from unittest.mock import patch - -import autopep8 -from flake8.api.legacy import get_style_guide - - -def get_python_filepaths(): - """Helper to retrieve paths of Python files.""" - python_paths = ['setup.py'] - for root in ['ops', 'test']: - for dirpath, dirnames, filenames in os.walk(root): - for filename in filenames: - if filename.endswith(".py"): - python_paths.append(os.path.join(dirpath, filename)) - return python_paths - - -class InfrastructureTests(unittest.TestCase): - - def test_pep8(self): - # verify all files are nicely styled - python_filepaths = get_python_filepaths() - style_guide = get_style_guide() - fake_stdout = io.StringIO() - with patch('sys.stdout', fake_stdout): - report = style_guide.check_files(python_filepaths) - - # if flake8 didnt' report anything, we're done - if report.total_errors == 0: - return - - # grab on which files we have issues - flake8_issues = fake_stdout.getvalue().split('\n') - broken_filepaths = {item.split(':')[0] for item in flake8_issues if item} - - # give hints to the developer on how files' style could be improved - options = autopep8.parse_args(['']) - options.aggressive = 1 - options.diff = True - options.max_line_length = 99 - - issues = [] - for filepath in broken_filepaths: - diff = autopep8.fix_file(filepath, options=options) - if diff: - issues.append(diff) - - report = ["Please fix files as suggested by autopep8:"] + issues - report += ["\n-- Original flake8 reports:"] + flake8_issues - self.fail("\n".join(report)) - - def test_quote_backslashes(self): - # ensure we're not using unneeded backslash to escape strings - issues = [] - for filepath in get_python_filepaths(): - with open(filepath, "rt", encoding="utf8") as fh: - for idx, line in enumerate(fh, 1): - if (r'\"' in line or r"\'" in line) and "NOQA" not in line: - issues.append((filepath, idx, line.rstrip())) - if issues: - msgs = ["{}:{:d}:{}".format(*issue) for issue in issues] - self.fail("Spurious backslashes found, please fix these quotings:\n" + "\n".join(msgs)) - - def test_ensure_copyright(self): - # all non-empty Python files must have a proper copyright somewhere in the first 5 lines - issues = [] - regex = re.compile(r"# Copyright \d\d\d\d(-\d\d\d\d)? Canonical Ltd.\n") - for filepath in get_python_filepaths(): - if os.stat(filepath).st_size == 0: - continue - - with open(filepath, "rt", encoding="utf8") as fh: - for line in itertools.islice(fh, 5): - if regex.match(line): - break - else: - issues.append(filepath) - if issues: - self.fail("Please add copyright headers to the following files:\n" + "\n".join(issues)) - - -class ImportersTestCase(unittest.TestCase): - - template = "from ops import {module_name}" - - def test_imports(self): - mod_names = [ - 'charm', - 'framework', - 'main', - 'model', - 'testing', - ] - - for name in mod_names: - with self.subTest(name=name): - self.check(name) - - def check(self, name): - """Helper function to run the test.""" - _, testfile = tempfile.mkstemp() - self.addCleanup(os.unlink, testfile) - - with open(testfile, 'wt', encoding='utf8') as fh: - fh.write(self.template.format(module_name=name)) - - proc = subprocess.run([sys.executable, testfile], env={'PYTHONPATH': os.getcwd()}) - self.assertEqual(proc.returncode, 0) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py deleted file mode 100755 index d19fd600..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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. - -import unittest - -from ops.jujuversion import JujuVersion - - -class TestJujuVersion(unittest.TestCase): - - def test_parsing(self): - test_cases = [ - ("0.0.0", 0, 0, '', 0, 0), - ("0.0.2", 0, 0, '', 2, 0), - ("0.1.0", 0, 1, '', 0, 0), - ("0.2.3", 0, 2, '', 3, 0), - ("10.234.3456", 10, 234, '', 3456, 0), - ("10.234.3456.1", 10, 234, '', 3456, 1), - ("1.21-alpha12", 1, 21, 'alpha', 12, 0), - ("1.21-alpha1.34", 1, 21, 'alpha', 1, 34), - ("2.7", 2, 7, '', 0, 0) - ] - - for vs, major, minor, tag, patch, build in test_cases: - v = JujuVersion(vs) - self.assertEqual(v.major, major) - self.assertEqual(v.minor, minor) - self.assertEqual(v.tag, tag) - self.assertEqual(v.patch, patch) - self.assertEqual(v.build, build) - - def test_parsing_errors(self): - invalid_versions = [ - "xyz", - "foo.bar", - "foo.bar.baz", - "dead.beef.ca.fe", - "1234567890.2.1", # The major version is too long. - "0.2..1", # Two periods next to each other. - "1.21.alpha1", # Tag comes after period. - "1.21-alpha", # No patch number but a tag is present. - "1.21-alpha1beta", # Non-numeric string after the patch number. - "1.21-alpha-dev", # Tag duplication. - "1.21-alpha_dev3", # Underscore in a tag. - "1.21-alpha123dev3", # Non-numeric string after the patch number. - ] - for v in invalid_versions: - with self.assertRaises(RuntimeError): - JujuVersion(v) - - def test_equality(self): - test_cases = [ - ("1.0.0", "1.0.0", True), - ("01.0.0", "1.0.0", True), - ("10.0.0", "9.0.0", False), - ("1.0.0", "1.0.1", False), - ("1.0.1", "1.0.0", False), - ("1.0.0", "1.1.0", False), - ("1.1.0", "1.0.0", False), - ("1.0.0", "2.0.0", False), - ("1.2-alpha1", "1.2.0", False), - ("1.2-alpha2", "1.2-alpha1", False), - ("1.2-alpha2.1", "1.2-alpha2", False), - ("1.2-alpha2.2", "1.2-alpha2.1", False), - ("1.2-beta1", "1.2-alpha1", False), - ("1.2-beta1", "1.2-alpha2.1", False), - ("1.2-beta1", "1.2.0", False), - ("1.2.1", "1.2.0", False), - ("2.0.0", "1.0.0", False), - ("2.0.0.0", "2.0.0", True), - ("2.0.0.0", "2.0.0.0", True), - ("2.0.0.1", "2.0.0.0", False), - ("2.0.1.10", "2.0.0.0", False), - ] - - for a, b, expected in test_cases: - self.assertEqual(JujuVersion(a) == JujuVersion(b), expected) - self.assertEqual(JujuVersion(a) == b, expected) - - def test_comparison(self): - test_cases = [ - ("1.0.0", "1.0.0", False, True), - ("01.0.0", "1.0.0", False, True), - ("10.0.0", "9.0.0", False, False), - ("1.0.0", "1.0.1", True, True), - ("1.0.1", "1.0.0", False, False), - ("1.0.0", "1.1.0", True, True), - ("1.1.0", "1.0.0", False, False), - ("1.0.0", "2.0.0", True, True), - ("1.2-alpha1", "1.2.0", True, True), - ("1.2-alpha2", "1.2-alpha1", False, False), - ("1.2-alpha2.1", "1.2-alpha2", False, False), - ("1.2-alpha2.2", "1.2-alpha2.1", False, False), - ("1.2-beta1", "1.2-alpha1", False, False), - ("1.2-beta1", "1.2-alpha2.1", False, False), - ("1.2-beta1", "1.2.0", True, True), - ("1.2.1", "1.2.0", False, False), - ("2.0.0", "1.0.0", False, False), - ("2.0.0.0", "2.0.0", False, True), - ("2.0.0.0", "2.0.0.0", False, True), - ("2.0.0.1", "2.0.0.0", False, False), - ("2.0.1.10", "2.0.0.0", False, False), - ] - - for a, b, expected_strict, expected_weak in test_cases: - self.assertEqual(JujuVersion(a) < JujuVersion(b), expected_strict) - self.assertEqual(JujuVersion(a) <= JujuVersion(b), expected_weak) - self.assertEqual(JujuVersion(b) > JujuVersion(a), expected_strict) - self.assertEqual(JujuVersion(b) >= JujuVersion(a), expected_weak) - # Implicit conversion. - self.assertEqual(JujuVersion(a) < b, expected_strict) - self.assertEqual(JujuVersion(a) <= b, expected_weak) - self.assertEqual(b > JujuVersion(a), expected_strict) - self.assertEqual(b >= JujuVersion(a), expected_weak) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_log.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_log.py deleted file mode 100644 index b7f74d5c..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_log.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/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. - -import io -import unittest -from unittest.mock import patch -import importlib - -import logging -import ops.log - - -class FakeModelBackend: - - def __init__(self): - self._calls = [] - - def calls(self, clear=False): - calls = self._calls - if clear: - self._calls = [] - return calls - - def juju_log(self, message, level): - self._calls.append((message, level)) - - -def reset_logging(): - logging.shutdown() - importlib.reload(logging) - - -class TestLogging(unittest.TestCase): - - def setUp(self): - self.backend = FakeModelBackend() - - reset_logging() - self.addCleanup(reset_logging) - - def test_default_logging(self): - ops.log.setup_root_logging(self.backend) - - logger = logging.getLogger() - self.assertEqual(logger.level, logging.DEBUG) - self.assertIsInstance(logger.handlers[0], ops.log.JujuLogHandler) - - test_cases = [( - lambda: logger.critical('critical'), [('CRITICAL', 'critical')] - ), ( - lambda: logger.error('error'), [('ERROR', 'error')] - ), ( - lambda: logger.warning('warning'), [('WARNING', 'warning')] - ), ( - lambda: logger.info('info'), [('INFO', 'info')] - ), ( - lambda: logger.debug('debug'), [('DEBUG', 'debug')] - )] - - for do, res in test_cases: - do() - calls = self.backend.calls(clear=True) - self.assertEqual(calls, res) - - def test_handler_filtering(self): - logger = logging.getLogger() - logger.setLevel(logging.INFO) - logger.addHandler(ops.log.JujuLogHandler(self.backend, logging.WARNING)) - logger.info('foo') - self.assertEqual(self.backend.calls(), []) - logger.warning('bar') - self.assertEqual(self.backend.calls(), [('WARNING', 'bar')]) - - def test_no_stderr_without_debug(self): - buffer = io.StringIO() - with patch('sys.stderr', buffer): - ops.log.setup_root_logging(self.backend, debug=False) - logger = logging.getLogger() - logger.debug('debug message') - logger.info('info message') - logger.warning('warning message') - logger.critical('critical message') - self.assertEqual( - self.backend.calls(), - [('DEBUG', 'debug message'), - ('INFO', 'info message'), - ('WARNING', 'warning message'), - ('CRITICAL', 'critical message'), - ]) - self.assertEqual(buffer.getvalue(), "") - - def test_debug_logging(self): - buffer = io.StringIO() - with patch('sys.stderr', buffer): - ops.log.setup_root_logging(self.backend, debug=True) - logger = logging.getLogger() - logger.debug('debug message') - logger.info('info message') - logger.warning('warning message') - logger.critical('critical message') - self.assertEqual( - self.backend.calls(), - [('DEBUG', 'debug message'), - ('INFO', 'info message'), - ('WARNING', 'warning message'), - ('CRITICAL', 'critical message'), - ]) - self.assertRegex( - buffer.getvalue(), - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d DEBUG debug message\n" - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d INFO info message\n" - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d WARNING warning message\n" - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d CRITICAL critical message\n" - ) - - def test_reduced_logging(self): - ops.log.setup_root_logging(self.backend) - logger = logging.getLogger() - logger.setLevel(logging.WARNING) - logger.debug('debug') - logger.info('info') - logger.warning('warning') - self.assertEqual(self.backend.calls(), [('WARNING', 'warning')]) - - -if __name__ == '__main__': - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_main.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_main.py deleted file mode 100755 index 0703b88a..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_main.py +++ /dev/null @@ -1,675 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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. - -import abc -import base64 -import logging -import os -import pickle -import shutil -import subprocess -import sys -import tempfile -import unittest -import importlib.util -from pathlib import Path - -from ops.charm import ( - CharmBase, - CharmEvents, - HookEvent, - InstallEvent, - StartEvent, - ConfigChangedEvent, - UpgradeCharmEvent, - UpdateStatusEvent, - LeaderSettingsChangedEvent, - RelationJoinedEvent, - RelationChangedEvent, - RelationDepartedEvent, - RelationBrokenEvent, - RelationEvent, - StorageAttachedEvent, - ActionEvent, - CollectMetricsEvent, -) - -from .test_helpers import fake_script, fake_script_calls - -# This relies on the expected repository structure to find a path to -# source of the charm under test. -TEST_CHARM_DIR = Path(__file__ + '/../charms/test_main').resolve() - -logger = logging.getLogger(__name__) - - -class SymlinkTargetError(Exception): - pass - - -class EventSpec: - def __init__(self, event_type, event_name, env_var=None, - relation_id=None, remote_app=None, remote_unit=None, - charm_config=None): - self.event_type = event_type - self.event_name = event_name - self.env_var = env_var - self.relation_id = relation_id - self.remote_app = remote_app - self.remote_unit = remote_unit - self.charm_config = charm_config - - -class TestMain(abc.ABC): - - @abc.abstractmethod - def _setup_entry_point(self, directory, entry_point): - """Set up the given entry point in the given directory. - - If not using dispatch, that would be a symlink / - pointing at src/charm.py; if using dispatch that would be the dispatch - symlink. It could also not be a symlink... - """ - return NotImplemented - - @abc.abstractmethod - def _call_event(self, rel_path, env): - """Set up the environment and call (i.e. run) the given event.""" - return NotImplemented - - @abc.abstractmethod - def test_setup_event_links(self): - """Test auto-creation of symlinks caused by initial events. - - Depending on the combination of dispatch and non-dispatch, this should - be checking for the creation or the _lack_ of creation, as appropriate. - """ - return NotImplemented - - def setUp(self): - self._setup_charm_dir() - - _, tmp_file = tempfile.mkstemp() - self._state_file = Path(tmp_file) - self.addCleanup(self._state_file.unlink) - - # Relations events are defined dynamically and modify the class attributes. - # We use a subclass temporarily to prevent these side effects from leaking. - class TestCharmEvents(CharmEvents): - pass - CharmBase.on = TestCharmEvents() - - def cleanup(): - shutil.rmtree(str(self.JUJU_CHARM_DIR)) - CharmBase.on = CharmEvents() - self.addCleanup(cleanup) - - fake_script(self, 'juju-log', "exit 0") - - # set to something other than None for tests that care - self.stdout = None - self.stderr = None - - def _setup_charm_dir(self): - self.JUJU_CHARM_DIR = Path(tempfile.mkdtemp()) / 'test_main' - self.hooks_dir = self.JUJU_CHARM_DIR / 'hooks' - charm_path = str(self.JUJU_CHARM_DIR / 'src/charm.py') - self.charm_exec_path = os.path.relpath(charm_path, - str(self.hooks_dir)) - shutil.copytree(str(TEST_CHARM_DIR), str(self.JUJU_CHARM_DIR)) - - charm_spec = importlib.util.spec_from_file_location("charm", charm_path) - self.charm_module = importlib.util.module_from_spec(charm_spec) - charm_spec.loader.exec_module(self.charm_module) - - self._prepare_initial_hooks() - - def _prepare_initial_hooks(self): - initial_hooks = ('install', 'start', 'upgrade-charm', 'disks-storage-attached') - self.hooks_dir.mkdir() - for hook in initial_hooks: - self._setup_entry_point(self.hooks_dir, hook) - - def _prepare_actions(self): - actions_meta = ''' -foo-bar: - description: Foos the bar. - title: foo-bar - params: - foo-name: - type: string - description: A foo name to bar. - silent: - type: boolean - description: - default: false - required: - - foo-name -start: - description: Start the unit.''' - actions_dir_name = 'actions' - actions_meta_file = 'actions.yaml' - - with (self.JUJU_CHARM_DIR / actions_meta_file).open('w+t') as f: - f.write(actions_meta) - actions_dir = self.JUJU_CHARM_DIR / actions_dir_name - actions_dir.mkdir() - for action_name in ('start', 'foo-bar'): - self._setup_entry_point(actions_dir, action_name) - - def _read_and_clear_state(self): - state = None - if self._state_file.stat().st_size: - with self._state_file.open('r+b') as state_file: - state = pickle.load(state_file) - state_file.truncate(0) - return state - - def _simulate_event(self, event_spec): - env = { - 'PATH': "{}:{}".format(Path(__file__).parent / 'bin', os.environ['PATH']), - 'JUJU_CHARM_DIR': str(self.JUJU_CHARM_DIR), - 'JUJU_UNIT_NAME': 'test_main/0', - 'CHARM_CONFIG': event_spec.charm_config, - } - if issubclass(event_spec.event_type, RelationEvent): - rel_name = event_spec.event_name.split('_')[0] - env.update({ - 'JUJU_RELATION': rel_name, - 'JUJU_RELATION_ID': str(event_spec.relation_id), - }) - remote_app = event_spec.remote_app - # For juju < 2.7 app name is extracted from JUJU_REMOTE_UNIT. - if remote_app is not None: - env['JUJU_REMOTE_APP'] = remote_app - - remote_unit = event_spec.remote_unit - if remote_unit is None: - remote_unit = '' - - env['JUJU_REMOTE_UNIT'] = remote_unit - else: - env.update({ - 'JUJU_REMOTE_UNIT': '', - 'JUJU_REMOTE_APP': '', - }) - if issubclass(event_spec.event_type, ActionEvent): - event_filename = event_spec.event_name[:-len('_action')].replace('_', '-') - env.update({ - event_spec.env_var: event_filename, - }) - if event_spec.env_var == 'JUJU_ACTION_NAME': - event_dir = 'actions' - else: - raise RuntimeError('invalid envar name specified for a action event') - else: - event_filename = event_spec.event_name.replace('_', '-') - event_dir = 'hooks' - - self._call_event(Path(event_dir, event_filename), env) - return self._read_and_clear_state() - - def test_event_reemitted(self): - # base64 encoding is used to avoid null bytes. - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - # First run "install" to make sure all hooks are set up. - state = self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [InstallEvent]) - - state = self._simulate_event(EventSpec(ConfigChangedEvent, 'config-changed', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [ConfigChangedEvent]) - - # Re-emit should pick the deferred config-changed. - state = self._simulate_event(EventSpec(UpdateStatusEvent, 'update-status', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [ConfigChangedEvent, UpdateStatusEvent]) - - def test_no_reemission_on_collect_metrics(self): - # base64 encoding is used to avoid null bytes. - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - fake_script(self, 'add-metric', 'exit 0') - - # First run "install" to make sure all hooks are set up. - state = self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [InstallEvent]) - - state = self._simulate_event(EventSpec(ConfigChangedEvent, 'config-changed', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [ConfigChangedEvent]) - - # Re-emit should not pick the deferred config-changed because - # collect-metrics runs in a restricted context. - state = self._simulate_event(EventSpec(CollectMetricsEvent, 'collect-metrics', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [CollectMetricsEvent]) - - def test_multiple_events_handled(self): - self._prepare_actions() - - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - actions_charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - 'USE_ACTIONS': True, - })) - - fake_script(self, 'action-get', "echo '{}'") - - # Sample events with a different amount of dashes used - # and with endpoints from different sections of metadata.yaml - events_under_test = [( - EventSpec(InstallEvent, 'install', - charm_config=charm_config), - {}, - ), ( - EventSpec(StartEvent, 'start', - charm_config=charm_config), - {}, - ), ( - EventSpec(UpdateStatusEvent, 'update_status', - charm_config=charm_config), - {}, - ), ( - EventSpec(LeaderSettingsChangedEvent, 'leader_settings_changed', - charm_config=charm_config), - {}, - ), ( - EventSpec(RelationJoinedEvent, 'db_relation_joined', - relation_id=1, - remote_app='remote', remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'db', - 'relation_id': 1, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationChangedEvent, 'mon_relation_changed', - relation_id=2, - remote_app='remote', remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationChangedEvent, 'mon_relation_changed', - relation_id=2, - remote_app='remote', remote_unit=None, - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': None}, - ), ( - EventSpec(RelationDepartedEvent, 'mon_relation_departed', - relation_id=2, - remote_app='remote', remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationBrokenEvent, 'ha_relation_broken', - relation_id=3, - charm_config=charm_config), - {'relation_name': 'ha', - 'relation_id': 3}, - ), ( - # Events without a remote app specified (for Juju < 2.7). - EventSpec(RelationJoinedEvent, 'db_relation_joined', - relation_id=1, - remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'db', - 'relation_id': 1, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationChangedEvent, 'mon_relation_changed', - relation_id=2, - remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationDepartedEvent, 'mon_relation_departed', - relation_id=2, - remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(ActionEvent, 'start_action', - env_var='JUJU_ACTION_NAME', - charm_config=actions_charm_config), - {}, - ), ( - EventSpec(ActionEvent, 'foo_bar_action', - env_var='JUJU_ACTION_NAME', - charm_config=actions_charm_config), - {}, - )] - - logger.debug('Expected events %s', events_under_test) - - # First run "install" to make sure all hooks are set up. - self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - - # Simulate hook executions for every event. - for event_spec, expected_event_data in events_under_test: - state = self._simulate_event(event_spec) - - state_key = 'on_' + event_spec.event_name - handled_events = state.get(state_key, []) - - # Make sure that a handler for that event was called once. - self.assertEqual(len(handled_events), 1) - # Make sure the event handled by the Charm has the right type. - handled_event_type = handled_events[0] - self.assertEqual(handled_event_type, event_spec.event_type) - - self.assertEqual(state['observed_event_types'], [event_spec.event_type]) - - if event_spec.event_name in expected_event_data: - self.assertEqual(state[event_spec.event_name + '_data'], - expected_event_data[event_spec.event_name]) - - def test_event_not_implemented(self): - """Make sure events without implementation do not cause non-zero exit. - """ - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - # Simulate a scenario where there is a symlink for an event that - # a charm does not know how to handle. - hook_path = self.JUJU_CHARM_DIR / 'hooks/not-implemented-event' - # This will be cleared up in tearDown. - hook_path.symlink_to('install') - - try: - self._simulate_event(EventSpec(HookEvent, 'not-implemented-event', - charm_config=charm_config)) - except subprocess.CalledProcessError: - self.fail('Event simulation for an unsupported event' - ' results in a non-zero exit code returned') - - def test_collect_metrics(self): - indicator_file = self.JUJU_CHARM_DIR / 'indicator' - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - 'INDICATOR_FILE': indicator_file - })) - fake_script(self, 'add-metric', 'exit 0') - fake_script(self, 'juju-log', 'exit 0') - self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - # Clear the calls during 'install' - fake_script_calls(self, clear=True) - self._simulate_event(EventSpec(CollectMetricsEvent, 'collect_metrics', - charm_config=charm_config)) - self.assertEqual( - fake_script_calls(self), - [['juju-log', '--log-level', 'DEBUG', 'Emitting Juju event collect_metrics'], - ['add-metric', '--labels', 'bar=4.2', 'foo=42']]) - - def test_logger(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - 'USE_LOG_ACTIONS': True, - })) - fake_script(self, 'action-get', "echo '{}'") - actions_yaml = self.JUJU_CHARM_DIR / 'actions.yaml' - actions_yaml.write_text( - ''' -log_critical: {} -log_error: {} -log_warning: {} -log_info: {} -log_debug: {} - ''') - - test_cases = [( - EventSpec(ActionEvent, 'log_critical_action', env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'CRITICAL', 'super critical'], - ), ( - EventSpec(ActionEvent, 'log_error_action', - env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'ERROR', 'grave error'], - ), ( - EventSpec(ActionEvent, 'log_warning_action', - env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'WARNING', 'wise warning'], - ), ( - EventSpec(ActionEvent, 'log_info_action', - env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'INFO', 'useful info'], - )] - - # Set up action symlinks. - self._simulate_event(EventSpec(InstallEvent, 'install', - charm_config=charm_config)) - - for event_spec, calls in test_cases: - self._simulate_event(event_spec) - self.assertIn(calls, fake_script_calls(self, clear=True)) - - -class TestMainWithNoDispatch(TestMain, unittest.TestCase): - def _setup_entry_point(self, directory, entry_point): - path = directory / entry_point - path.symlink_to(self.charm_exec_path) - - def _call_event(self, rel_path, env): - event_file = self.JUJU_CHARM_DIR / rel_path - # Note that sys.executable is used to make sure we are using the same - # interpreter for the child process to support virtual environments. - subprocess.run( - [sys.executable, str(event_file)], - check=True, env=env, cwd=str(self.JUJU_CHARM_DIR)) - - def test_setup_event_links(self): - """Test auto-creation of symlinks caused by initial events. - """ - all_event_hooks = ['hooks/' + e.replace("_", "-") - for e in self.charm_module.Charm.on.events().keys()] - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - initial_events = { - EventSpec(InstallEvent, 'install', charm_config=charm_config), - EventSpec(StorageAttachedEvent, 'disks-storage-attached', charm_config=charm_config), - EventSpec(StartEvent, 'start', charm_config=charm_config), - EventSpec(UpgradeCharmEvent, 'upgrade-charm', charm_config=charm_config), - } - - def _assess_event_links(event_spec): - self.assertTrue(self.hooks_dir / event_spec.event_name in self.hooks_dir.iterdir()) - for event_hook in all_event_hooks: - self.assertTrue((self.JUJU_CHARM_DIR / event_hook).exists(), - 'Missing hook: ' + event_hook) - self.assertEqual(os.readlink(str(self.JUJU_CHARM_DIR / event_hook)), - self.charm_exec_path) - - for initial_event in initial_events: - self._setup_charm_dir() - - self._simulate_event(initial_event) - _assess_event_links(initial_event) - # Make sure it is idempotent. - self._simulate_event(initial_event) - _assess_event_links(initial_event) - - def test_setup_action_links(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - actions_yaml = self.JUJU_CHARM_DIR / 'actions.yaml' - actions_yaml.write_text('test: {}') - self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - action_hook = self.JUJU_CHARM_DIR / 'actions' / 'test' - self.assertTrue(action_hook.exists()) - - -class TestMainWithDispatch(TestMain, unittest.TestCase): - def _setup_entry_point(self, directory, entry_point): - path = self.JUJU_CHARM_DIR / 'dispatch' - if not path.exists(): - path.symlink_to('src/charm.py') - - def _call_event(self, rel_path, env): - env["JUJU_DISPATCH_PATH"] = str(rel_path) - dispatch = self.JUJU_CHARM_DIR / 'dispatch' - subprocess.run( - [sys.executable, str(dispatch)], - stdout=self.stdout, - stderr=self.stderr, - check=True, env=env, cwd=str(self.JUJU_CHARM_DIR)) - - def test_setup_event_links(self): - """Test auto-creation of symlinks caused by initial events does _not_ happen when using dispatch. - """ - all_event_hooks = ['hooks/' + e.replace("_", "-") - for e in self.charm_module.Charm.on.events().keys()] - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - initial_events = { - EventSpec(InstallEvent, 'install', charm_config=charm_config), - EventSpec(StorageAttachedEvent, 'disks-storage-attached', charm_config=charm_config), - EventSpec(StartEvent, 'start', charm_config=charm_config), - EventSpec(UpgradeCharmEvent, 'upgrade-charm', charm_config=charm_config), - } - - def _assess_event_links(event_spec): - self.assertNotIn(self.hooks_dir / event_spec.event_name, self.hooks_dir.iterdir()) - for event_hook in all_event_hooks: - self.assertFalse((self.JUJU_CHARM_DIR / event_hook).exists(), - 'Spurious hook: ' + event_hook) - - for initial_event in initial_events: - self._setup_charm_dir() - - self._simulate_event(initial_event) - _assess_event_links(initial_event) - - def test_hook_and_dispatch(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - self.fake_script_path = self.hooks_dir - fake_script(self, 'install', 'exit 0') - state = self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - - # the script was called, *and*, the .on. was called - self.assertEqual(fake_script_calls(self), [['install', '']]) - self.assertEqual(state['observed_event_types'], [InstallEvent]) - - def test_hook_and_dispatch_with_failing_hook(self): - self.stdout = self.stderr = tempfile.TemporaryFile() - self.addCleanup(self.stdout.close) - - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - old_path = self.fake_script_path - self.fake_script_path = self.hooks_dir - fake_script(self, 'install', 'exit 42') - event = EventSpec(InstallEvent, 'install', charm_config=charm_config) - with self.assertRaises(subprocess.CalledProcessError): - self._simulate_event(event) - self.fake_script_path = old_path - - self.stdout.seek(0) - self.assertEqual(self.stdout.read(), b'') - calls = fake_script_calls(self) - self.assertEqual(len(calls), 1, 'unexpect call result: {}'.format(calls)) - self.assertEqual(len(calls[0]), 4, 'unexpect call result: {}'.format(calls[0])) - self.assertEqual( - calls[0][:3], - ['juju-log', '--log-level', 'WARNING'] - ) - self.assertRegex(calls[0][3], r'hook /\S+/install exited with status 42') - - def test_hook_and_dispatch_but_hook_is_dispatch(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - event = EventSpec(InstallEvent, 'install', charm_config=charm_config) - hook_path = self.hooks_dir / 'install' - for ((rel, ind), path) in { - # relative and indirect - (True, True): Path('../dispatch'), - # relative and direct - (True, False): Path(self.charm_exec_path), - # absolute and direct - (False, False): (self.hooks_dir / self.charm_exec_path).resolve(), - # absolute and indirect - (False, True): self.JUJU_CHARM_DIR / 'dispatch', - }.items(): - with self.subTest(path=path, rel=rel, ind=ind): - # sanity check - self.assertEqual(path.is_absolute(), not rel) - self.assertEqual(path.name == 'dispatch', ind) - try: - hook_path.symlink_to(path) - - state = self._simulate_event(event) - - # the .on. was only called once - self.assertEqual(state['observed_event_types'], [InstallEvent]) - self.assertEqual(state['on_install'], [InstallEvent]) - finally: - hook_path.unlink() - - -# TODO: this does not work -# class TestMainWithDispatchAsScript(TestMainWithDispatch): -# """Here dispatch is a script that execs the charm.py instead of a symlink. -# """ -# def _setup_entry_point(self, directory, entry_point): -# path = self.JUJU_CHARM_DIR / 'dispatch' -# if not path.exists(): -# path.write_text('#!/bin/sh\nexec "{}" "{}"\n'.format( -# sys.executable, -# self.JUJU_CHARM_DIR / 'src/charm.py')) -# path.chmod(0o755) - -# def _call_event(self, rel_path, env): -# env["JUJU_DISPATCH_PATH"] = str(rel_path) -# dispatch = self.JUJU_CHARM_DIR / 'dispatch' -# subprocess.check_call([str(dispatch)], -# env=env, cwd=str(self.JUJU_CHARM_DIR)) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_model.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_model.py deleted file mode 100755 index 660176a4..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_model.py +++ /dev/null @@ -1,1288 +0,0 @@ -#!/usr/bin/python3 -# Copyright 2019 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. - -import os -import pathlib -import unittest -import json -import ipaddress -from collections import OrderedDict - -import ops.model -import ops.charm -from ops.charm import RelationMeta - -from test.test_helpers import fake_script, fake_script_calls - - -class TestModel(unittest.TestCase): - - def setUp(self): - def restore_env(env): - os.environ.clear() - os.environ.update(env) - self.addCleanup(restore_env, os.environ.copy()) - - os.environ['JUJU_UNIT_NAME'] = 'myapp/0' - - self.backend = ops.model.ModelBackend() - meta = ops.charm.CharmMeta() - meta.relations = { - 'db0': RelationMeta('provides', 'db0', {'interface': 'db0', 'scope': 'global'}), - 'db1': RelationMeta('requires', 'db1', {'interface': 'db1', 'scope': 'global'}), - 'db2': RelationMeta('peers', 'db2', {'interface': 'db2', 'scope': 'global'}), - } - self.model = ops.model.Model('myapp/0', meta, self.backend) - fake_script(self, 'relation-ids', """([ "$1" = db0 ] && echo '["db0:4"]') || echo '[]'""") - - def test_model(self): - self.assertIs(self.model.app, self.model.unit.app) - - def test_relations_keys(self): - fake_script(self, 'relation-ids', - """[ "$1" = db2 ] && echo '["db2:5", "db2:6"]' || echo '[]'""") - fake_script(self, 'relation-list', - """ -case "$2" in - 5) - echo '["remoteapp1/0", "remoteapp1/1"]' - ;; - 6) - echo '["remoteapp2/0"]' - ;; - *) - exit 2 - ;; -esac -""") - - for relation in self.model.relations['db2']: - self.assertIn(self.model.unit, relation.data) - unit_from_rel = next(filter(lambda u: u.name == 'myapp/0', relation.data.keys())) - self.assertIs(self.model.unit, unit_from_rel) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db2', '--format=json'], - ['relation-list', '-r', '5', '--format=json'], - ['relation-list', '-r', '6', '--format=json'] - ]) - - def test_get_relation(self): - err_msg = 'ERROR invalid value "$2" for option -r: relation not found' - - fake_script(self, 'relation-ids', ''' - case "$1" in - db1) - echo '["db1:4"]' - ;; - db2) - echo '["db2:5", "db2:6"]' - ;; - *) - echo '[]' - ;; - esac - ''') - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0"]' - else - echo {} >&2 - exit 2 - fi - '''.format(err_msg)) - fake_script(self, 'relation-get', - """echo {} >&2 ; exit 2""".format(err_msg)) - - with self.assertRaises(ops.model.ModelError): - self.model.get_relation('db1', 'db1:4') - db1_4 = self.model.get_relation('db1', 4) - self.assertIsInstance(db1_4, ops.model.Relation) - dead_rel = self.model.get_relation('db1', 7) - self.assertIsInstance(dead_rel, ops.model.Relation) - self.assertEqual(set(dead_rel.data.keys()), {self.model.unit, self.model.unit.app}) - self.assertEqual(dead_rel.data[self.model.unit], {}) - self.assertIsNone(self.model.get_relation('db0')) - self.assertIs(self.model.get_relation('db1'), db1_4) - with self.assertRaises(ops.model.TooManyRelatedAppsError): - self.model.get_relation('db2') - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-list', '-r', '7', '--format=json'], - ['relation-get', '-r', '7', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-ids', 'db0', '--format=json'], - ['relation-ids', 'db2', '--format=json'], - ['relation-list', '-r', '5', '--format=json'], - ['relation-list', '-r', '6', '--format=json'] - ]) - - def test_peer_relation_app(self): - meta = ops.charm.CharmMeta() - meta.relations = {'dbpeer': RelationMeta('peers', 'dbpeer', - {'interface': 'dbpeer', 'scope': 'global'})} - self.model = ops.model.Model('myapp/0', meta, self.backend) - - err_msg = 'ERROR invalid value "$2" for option -r: relation not found' - fake_script(self, 'relation-ids', - '''([ "$1" = dbpeer ] && echo '["dbpeer:0"]') || echo "[]"''') - fake_script(self, 'relation-list', - '''([ "$2" = 0 ] && echo "[]") || (echo {} >&2 ; exit 2)'''.format(err_msg)) - - db1_4 = self.model.get_relation('dbpeer') - self.assertIs(db1_4.app, self.model.app) - - def test_remote_units_is_our(self): - fake_script(self, 'relation-ids', - """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', - """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""") - - for u in self.model.get_relation('db1').units: - self.assertFalse(u._is_our_unit) - self.assertFalse(u.app._is_our_app) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'] - ]) - - def test_our_unit_is_our(self): - self.assertTrue(self.model.unit._is_our_unit) - self.assertTrue(self.model.unit.app._is_our_app) - - def test_unit_relation_data(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', """ -if [ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]; then - echo '{"host": "remoteapp1-0"}' -else - exit 2 -fi -""") - - random_unit = self.model._cache.get(ops.model.Unit, 'randomunit/0') - with self.assertRaises(KeyError): - self.model.get_relation('db1').data[random_unit] - remoteapp1_0 = next(filter(lambda u: u.name == 'remoteapp1/0', - self.model.get_relation('db1').units)) - self.assertEqual(self.model.get_relation('db1').data[remoteapp1_0], - {'host': 'remoteapp1-0'}) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'remoteapp1/0', '--app=False', '--format=json'] - ]) - - def test_remote_app_relation_data(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = remoteapp1 ]; then - echo '{"secret": "cafedeadbeef"}' - else - exit 2 - fi - ''') - - # Try to get relation data for an invalid remote application. - random_app = self.model._cache.get(ops.model.Application, 'randomapp') - with self.assertRaises(KeyError): - self.model.get_relation('db1').data[random_app] - - remoteapp1 = self.model.get_relation('db1').app - self.assertEqual(self.model.get_relation('db1').data[remoteapp1], - {'secret': 'cafedeadbeef'}) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'remoteapp1', '--app=True', '--format=json'], - ]) - - def test_relation_data_modify_remote(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', """ -if [ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]; then - echo '{"host": "remoteapp1-0"}' -else - exit 2 -fi -""") - - rel_db1 = self.model.get_relation('db1') - remoteapp1_0 = next(filter(lambda u: u.name == 'remoteapp1/0', - self.model.get_relation('db1').units)) - # Force memory cache to be loaded. - self.assertIn('host', rel_db1.data[remoteapp1_0]) - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[remoteapp1_0]['foo'] = 'bar' - self.assertNotIn('foo', rel_db1.data[remoteapp1_0]) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'remoteapp1/0', '--app=False', '--format=json'] - ]) - - def test_relation_data_modify_our(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-set', '''[ "$2" = 4 ] && exit 0 || exit 2''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "bar"}' - else - exit 2 - fi - ''') - - rel_db1 = self.model.get_relation('db1') - # Force memory cache to be loaded. - self.assertIn('host', rel_db1.data[self.model.unit]) - rel_db1.data[self.model.unit]['host'] = 'bar' - self.assertEqual(rel_db1.data[self.model.unit]['host'], 'bar') - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-set', '-r', '4', 'host=bar', '--app=False'] - ]) - - def test_app_relation_data_modify_local_as_leader(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = myapp ]; then - echo '{"password": "deadbeefcafe"}' - else - exit 2 - fi - ''') - fake_script(self, 'relation-set', """[ "$2" = 4 ] && exit 0 || exit 2""") - fake_script(self, 'is-leader', 'echo true') - - local_app = self.model.unit.app - - rel_db1 = self.model.get_relation('db1') - self.assertEqual(rel_db1.data[local_app], {'password': 'deadbeefcafe'}) - - rel_db1.data[local_app]['password'] = 'foo' - - self.assertEqual(rel_db1.data[local_app]['password'], 'foo') - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp', '--app=True', '--format=json'], - ['is-leader', '--format=json'], - ['relation-set', '-r', '4', 'password=foo', '--app=True'], - ]) - - def test_app_relation_data_modify_local_as_minion(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = myapp ]; then - echo '{"password": "deadbeefcafe"}' - else - exit 2 - fi - ''') - fake_script(self, 'is-leader', 'echo false') - - local_app = self.model.unit.app - - rel_db1 = self.model.get_relation('db1') - self.assertEqual(rel_db1.data[local_app], {'password': 'deadbeefcafe'}) - - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[local_app]['password'] = 'foobar' - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp', '--app=True', '--format=json'], - ['is-leader', '--format=json'], - ]) - - def test_relation_data_del_key(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-set', '''[ "$2" = 4 ] && exit 0 || exit 2''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "bar"}' - else - exit 2 - fi - ''') - - rel_db1 = self.model.get_relation('db1') - # Force memory cache to be loaded. - self.assertIn('host', rel_db1.data[self.model.unit]) - del rel_db1.data[self.model.unit]['host'] - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{}' - else - exit 2 - fi - ''') - self.assertNotIn('host', rel_db1.data[self.model.unit]) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-set', '-r', '4', 'host=', '--app=False'] - ]) - - def test_relation_set_fail(self): - fake_script(self, 'relation-ids', """[ "$1" = db2 ] && echo '["db2:5"]' || echo '[]'""") - fake_script(self, 'relation-list', - """[ "$2" = 5 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', ''' - if [ "$2" = 5 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "myapp-0"}' - else - exit 2 - fi - ''') - fake_script(self, 'relation-set', 'exit 2') - - rel_db2 = self.model.relations['db2'][0] - # Force memory cache to be loaded. - self.assertIn('host', rel_db2.data[self.model.unit]) - with self.assertRaises(ops.model.ModelError): - rel_db2.data[self.model.unit]['host'] = 'bar' - self.assertEqual(rel_db2.data[self.model.unit]['host'], 'myapp-0') - with self.assertRaises(ops.model.ModelError): - del rel_db2.data[self.model.unit]['host'] - self.assertIn('host', rel_db2.data[self.model.unit]) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db2', '--format=json'], - ['relation-list', '-r', '5', '--format=json'], - ['relation-get', '-r', '5', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-set', '-r', '5', 'host=bar', '--app=False'], - ['relation-set', '-r', '5', 'host=', '--app=False'] - ]) - - def test_relation_get_set_is_app_arg(self): - self.backend = ops.model.ModelBackend() - - # No is_app provided. - with self.assertRaises(TypeError): - self.backend.relation_set(1, 'fookey', 'barval') - - with self.assertRaises(TypeError): - self.backend.relation_get(1, 'fooentity') - - # Invalid types for is_app. - for is_app_v in [None, 1, 2.0, 'a', b'beef']: - with self.assertRaises(TypeError): - self.backend.relation_set(1, 'fookey', 'barval', is_app=is_app_v) - - with self.assertRaises(TypeError): - self.backend.relation_get(1, 'fooentity', is_app=is_app_v) - - def test_relation_data_type_check(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', - """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "myapp-0"}' - else - exit 2 - fi - ''') - - rel_db1 = self.model.get_relation('db1') - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[self.model.unit]['foo'] = 1 - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[self.model.unit]['foo'] = {'foo': 'bar'} - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[self.model.unit]['foo'] = None - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'] - ]) - - def test_config(self): - fake_script(self, 'config-get', """echo '{"foo":"foo","bar":1,"qux":true}'""") - self.assertEqual(self.model.config, { - 'foo': 'foo', - 'bar': 1, - 'qux': True, - }) - with self.assertRaises(TypeError): - # Confirm that we cannot modify config values. - self.model.config['foo'] = 'bar' - - self.assertEqual(fake_script_calls(self), [['config-get', '--format=json']]) - - def test_is_leader(self): - def check_remote_units(): - fake_script(self, 'relation-ids', - """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - - fake_script(self, 'relation-list', - """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""") - - # Cannot determine leadership for remote units. - for u in self.model.get_relation('db1').units: - with self.assertRaises(RuntimeError): - u.is_leader() - - fake_script(self, 'is-leader', 'echo true') - self.assertTrue(self.model.unit.is_leader()) - - check_remote_units() - - # Create a new model and backend to drop a cached is-leader output. - self.backend = ops.model.ModelBackend() - meta = ops.charm.CharmMeta() - meta.relations = { - 'db0': RelationMeta('provides', 'db0', {'interface': 'db0', 'scope': 'global'}), - 'db1': RelationMeta('requires', 'db1', {'interface': 'db1', 'scope': 'global'}), - 'db2': RelationMeta('peers', 'db2', {'interface': 'db2', 'scope': 'global'}), - } - self.model = ops.model.Model('myapp/0', meta, self.backend) - - fake_script(self, 'is-leader', 'echo false') - self.assertFalse(self.model.unit.is_leader()) - - check_remote_units() - - self.assertEqual(fake_script_calls(self), [ - ['is-leader', '--format=json'], - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['is-leader', '--format=json'], - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ]) - - def test_is_leader_refresh(self): - fake_script(self, 'is-leader', 'echo false') - self.assertFalse(self.model.unit.is_leader()) - - # Change the leadership status and force a recheck. - fake_script(self, 'is-leader', 'echo true') - self.backend._leader_check_time = None - self.assertTrue(self.model.unit.is_leader()) - - # Force a recheck without changing the leadership status. - fake_script(self, 'is-leader', 'echo true') - self.backend._leader_check_time = None - self.assertTrue(self.model.unit.is_leader()) - - def test_workload_version(self): - fake_script(self, 'application-version-set', 'exit 0') - self.model.unit.set_workload_version('1.2.3') - self.assertEqual(fake_script_calls(self), [['application-version-set', '--', '1.2.3']]) - - def test_workload_version_invalid(self): - fake_script(self, 'application-version-set', 'exit 0') - with self.assertRaises(TypeError) as cm: - self.model.unit.set_workload_version(5) - self.assertEqual(str(cm.exception), "workload version must be a str, not int: 5") - self.assertEqual(fake_script_calls(self), []) - - def test_resources(self): - meta = ops.charm.CharmMeta() - meta.resources = {'foo': None, 'bar': None} - model = ops.model.Model('myapp/0', meta, self.backend) - - with self.assertRaises(RuntimeError): - model.resources.fetch('qux') - - fake_script(self, 'resource-get', 'exit 1') - with self.assertRaises(ops.model.ModelError): - model.resources.fetch('foo') - - fake_script(self, 'resource-get', - 'echo /var/lib/juju/agents/unit-test-0/resources/$1/$1.tgz') - self.assertEqual(model.resources.fetch('foo').name, 'foo.tgz') - self.assertEqual(model.resources.fetch('bar').name, 'bar.tgz') - - def test_pod_spec(self): - fake_script(self, 'pod-spec-set', """ - cat $2 > $(dirname $0)/spec.json - [[ -n $4 ]] && cat $4 > $(dirname $0)/k8s_res.json || true - """) - fake_script(self, 'is-leader', 'echo true') - spec_path = self.fake_script_path / 'spec.json' - k8s_res_path = self.fake_script_path / 'k8s_res.json' - - def check_calls(calls): - # There may 1 or 2 calls because of is-leader. - self.assertLessEqual(len(fake_calls), 2) - pod_spec_call = next(filter(lambda c: c[0] == 'pod-spec-set', calls)) - self.assertEqual(pod_spec_call[:2], ['pod-spec-set', '--file']) - - # 8 bytes are used as of python 3.4.0, see Python bug #12015. - # Other characters are from POSIX 3.282 (Portable Filename - # Character Set) a subset of which Python's mkdtemp uses. - self.assertRegex(pod_spec_call[2], '.*/tmp[A-Za-z0-9._-]{8}-pod-spec-set') - - self.model.pod.set_spec({'foo': 'bar'}) - self.assertEqual(spec_path.read_text(), '{"foo": "bar"}') - self.assertFalse(k8s_res_path.exists()) - - fake_calls = fake_script_calls(self, clear=True) - check_calls(fake_calls) - - self.model.pod.set_spec({'bar': 'foo'}, {'qux': 'baz'}) - self.assertEqual(spec_path.read_text(), '{"bar": "foo"}') - self.assertEqual(k8s_res_path.read_text(), '{"qux": "baz"}') - - fake_calls = fake_script_calls(self, clear=True) - check_calls(fake_calls) - - # Create a new model to drop is-leader caching result. - self.backend = ops.model.ModelBackend() - meta = ops.charm.CharmMeta() - self.model = ops.model.Model('myapp/0', meta, self.backend) - fake_script(self, 'is-leader', 'echo false') - with self.assertRaises(ops.model.ModelError): - self.model.pod.set_spec({'foo': 'bar'}) - - def test_base_status_instance_raises(self): - with self.assertRaises(TypeError): - ops.model.StatusBase('test') - - def test_active_message_default(self): - self.assertEqual(ops.model.ActiveStatus().message, '') - - def test_local_set_valid_unit_status(self): - test_cases = [( - ops.model.ActiveStatus('Green'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual(fake_script_calls(self, True), - [['status-set', '--application=False', 'active', 'Green']]), - ), ( - ops.model.MaintenanceStatus('Yellow'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual( - fake_script_calls(self, True), - [['status-set', '--application=False', 'maintenance', 'Yellow']]), - ), ( - ops.model.BlockedStatus('Red'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual(fake_script_calls(self, True), - [['status-set', '--application=False', 'blocked', 'Red']]), - ), ( - ops.model.WaitingStatus('White'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual(fake_script_calls(self, True), - [['status-set', '--application=False', 'waiting', 'White']]), - )] - - for target_status, setup_tools, check_tool_calls in test_cases: - setup_tools() - - self.model.unit.status = target_status - - self.assertEqual(self.model.unit.status, target_status) - - check_tool_calls() - - def test_local_set_valid_app_status(self): - fake_script(self, 'is-leader', 'echo true') - test_cases = [( - ops.model.ActiveStatus('Green'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'active', 'Green'], - fake_script_calls(self, True)), - ), ( - ops.model.MaintenanceStatus('Yellow'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'maintenance', 'Yellow'], - fake_script_calls(self, True)), - ), ( - ops.model.BlockedStatus('Red'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'blocked', 'Red'], - fake_script_calls(self, True)), - ), ( - ops.model.WaitingStatus('White'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'waiting', 'White'], - fake_script_calls(self, True)), - )] - - for target_status, setup_tools, check_tool_calls in test_cases: - setup_tools() - - self.model.app.status = target_status - - self.assertEqual(self.model.app.status, target_status) - - check_tool_calls() - - def test_set_app_status_non_leader_raises(self): - fake_script(self, 'is-leader', 'echo false') - - with self.assertRaises(RuntimeError): - self.model.app.status - - with self.assertRaises(RuntimeError): - self.model.app.status = ops.model.ActiveStatus() - - def test_local_set_invalid_status(self): - fake_script(self, 'status-set', 'exit 1') - fake_script(self, 'is-leader', 'echo true') - - with self.assertRaises(ops.model.ModelError): - self.model.unit.status = ops.model.UnknownStatus() - - self.assertEqual(fake_script_calls(self, True), [ - ['status-set', '--application=False', 'unknown', ''], - ]) - - with self.assertRaises(ops.model.ModelError): - self.model.app.status = ops.model.UnknownStatus() - - # A leadership check is needed for application status. - self.assertEqual(fake_script_calls(self, True), [ - ['is-leader', '--format=json'], - ['status-set', '--application=True', 'unknown', ''], - ]) - - def test_status_set_is_app_not_bool_raises(self): - self.backend = ops.model.ModelBackend() - - for is_app_v in [None, 1, 2.0, 'a', b'beef', object]: - with self.assertRaises(TypeError): - self.backend.status_set(ops.model.ActiveStatus, is_app=is_app_v) - - def test_remote_unit_status(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - - remote_unit = next(filter(lambda u: u.name == 'remoteapp1/0', - self.model.get_relation('db1').units)) - - test_statuses = ( - ops.model.UnknownStatus(), - ops.model.ActiveStatus('Green'), - ops.model.MaintenanceStatus('Yellow'), - ops.model.BlockedStatus('Red'), - ops.model.WaitingStatus('White'), - ) - - for target_status in test_statuses: - with self.assertRaises(RuntimeError): - remote_unit.status = target_status - - def test_remote_app_status(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - - remoteapp1 = self.model.get_relation('db1').app - - # Remote application status is always unknown. - self.assertIsInstance(remoteapp1.status, ops.model.UnknownStatus) - - test_statuses = ( - ops.model.UnknownStatus(), - ops.model.ActiveStatus(), - ops.model.MaintenanceStatus('Upgrading software'), - ops.model.BlockedStatus('Awaiting manual resolution'), - ops.model.WaitingStatus('Awaiting related app updates'), - ) - for target_status in test_statuses: - with self.assertRaises(RuntimeError): - remoteapp1.status = target_status - - self.assertEqual(fake_script_calls(self, clear=True), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ]) - - def test_storage(self): - meta = ops.charm.CharmMeta() - meta.storages = {'disks': None, 'data': None} - self.model = ops.model.Model('myapp/0', meta, self.backend) - - fake_script(self, 'storage-list', ''' - if [ "$1" = disks ]; then - echo '["disks/0", "disks/1"]' - else - echo '[]' - fi - ''') - fake_script(self, 'storage-get', ''' - if [ "$2" = disks/0 ]; then - echo '"/var/srv/disks/0"' - elif [ "$2" = disks/1 ]; then - echo '"/var/srv/disks/1"' - else - exit 2 - fi - ''') - fake_script(self, 'storage-add', '') - - self.assertEqual(len(self.model.storages), 2) - self.assertEqual(self.model.storages.keys(), meta.storages.keys()) - self.assertIn('disks', self.model.storages) - test_cases = { - 0: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/0')}, - 1: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/1')}, - } - for storage in self.model.storages['disks']: - self.assertEqual(storage.name, 'disks') - self.assertIn(storage.id, test_cases) - self.assertEqual(storage.name, test_cases[storage.id]['name']) - self.assertEqual(storage.location, test_cases[storage.id]['location']) - - self.assertEqual(fake_script_calls(self, clear=True), [ - ['storage-list', 'disks', '--format=json'], - ['storage-get', '-s', 'disks/0', 'location', '--format=json'], - ['storage-get', '-s', 'disks/1', 'location', '--format=json'], - ]) - - self.assertSequenceEqual(self.model.storages['data'], []) - self.model.storages.request('data', count=3) - self.assertEqual(fake_script_calls(self), [ - ['storage-list', 'data', '--format=json'], - ['storage-add', 'data=3'], - ]) - - # Try to add storage not present in charm metadata. - with self.assertRaises(ops.model.ModelError): - self.model.storages.request('deadbeef') - - # Invalid count parameter types. - for count_v in [None, False, 2.0, 'a', b'beef', object]: - with self.assertRaises(TypeError): - self.model.storages.request('data', count_v) - - -class TestModelBindings(unittest.TestCase): - - def setUp(self): - def restore_env(env): - os.environ.clear() - os.environ.update(env) - self.addCleanup(restore_env, os.environ.copy()) - - os.environ['JUJU_UNIT_NAME'] = 'myapp/0' - - meta = ops.charm.CharmMeta() - meta.relations = { - 'db0': RelationMeta('provides', 'db0', {'interface': 'db0', 'scope': 'global'}), - 'db1': RelationMeta('requires', 'db1', {'interface': 'db1', 'scope': 'global'}), - 'db2': RelationMeta('peers', 'db2', {'interface': 'db2', 'scope': 'global'}), - } - self.backend = ops.model.ModelBackend() - self.model = ops.model.Model('myapp/0', meta, self.backend) - - fake_script(self, 'relation-ids', - """([ "$1" = db0 ] && echo '["db0:4"]') || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - self.network_get_out = '''{ - "bind-addresses": [ - { - "mac-address": "de:ad:be:ef:ca:fe", - "interface-name": "lo", - "addresses": [ - { - "hostname": "", - "value": "192.0.2.2", - "cidr": "192.0.2.0/24" - }, - { - "hostname": "deadbeef.example", - "value": "dead:beef::1", - "cidr": "dead:beef::/64" - } - ] - }, - { - "mac-address": "", - "interface-name": "tun", - "addresses": [ - { - "hostname": "", - "value": "192.0.3.3", - "cidr": "" - }, - { - "hostname": "", - "value": "2001:db8::3", - "cidr": "" - }, - { - "hostname": "deadbeef.local", - "value": "fe80::1:1", - "cidr": "fe80::/64" - } - ] - } - ], - "egress-subnets": [ - "192.0.2.2/32", - "192.0.3.0/24", - "dead:beef::/64", - "2001:db8::3/128" - ], - "ingress-addresses": [ - "192.0.2.2", - "192.0.3.3", - "dead:beef::1", - "2001:db8::3" - ] -}''' - - def _check_binding_data(self, binding_name, binding): - self.assertEqual(binding.name, binding_name) - self.assertEqual(binding.network.bind_address, ipaddress.ip_address('192.0.2.2')) - self.assertEqual(binding.network.ingress_address, ipaddress.ip_address('192.0.2.2')) - # /32 and /128 CIDRs are valid one-address networks for IPv{4,6}Network types respectively. - self.assertEqual(binding.network.egress_subnets, [ipaddress.ip_network('192.0.2.2/32'), - ipaddress.ip_network('192.0.3.0/24'), - ipaddress.ip_network('dead:beef::/64'), - ipaddress.ip_network('2001:db8::3/128')]) - - for (i, (name, address, subnet)) in enumerate([ - ('lo', '192.0.2.2', '192.0.2.0/24'), - ('lo', 'dead:beef::1', 'dead:beef::/64'), - ('tun', '192.0.3.3', '192.0.3.3/32'), - ('tun', '2001:db8::3', '2001:db8::3/128'), - ('tun', 'fe80::1:1', 'fe80::/64')]): - self.assertEqual(binding.network.interfaces[i].name, name) - self.assertEqual(binding.network.interfaces[i].address, ipaddress.ip_address(address)) - self.assertEqual(binding.network.interfaces[i].subnet, ipaddress.ip_network(subnet)) - - def test_invalid_keys(self): - # Basic validation for passing invalid keys. - for name in (object, 0): - with self.assertRaises(ops.model.ModelError): - self.model.get_binding(name) - - def test_dead_relations(self): - fake_script( - self, - 'network-get', - ''' - if [ "$1" = db0 ] && [ "$2" = --format=json ]; then - echo '{}' - else - echo ERROR invalid value "$2" for option -r: relation not found >&2 - exit 2 - fi - '''.format(self.network_get_out)) - # Validate the behavior for dead relations. - binding = ops.model.Binding('db0', 42, self.model._backend) - self.assertEqual(binding.network.bind_address, ipaddress.ip_address('192.0.2.2')) - self.assertEqual(fake_script_calls(self, clear=True), [ - ['network-get', 'db0', '-r', '42', '--format=json'], - ['network-get', 'db0', '--format=json'], - ]) - - def test_binding_by_relation_name(self): - fake_script(self, 'network-get', - '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out)) - binding_name = 'db0' - expected_calls = [['network-get', 'db0', '--format=json']] - - binding = self.model.get_binding(binding_name) - self._check_binding_data(binding_name, binding) - self.assertEqual(fake_script_calls(self, clear=True), expected_calls) - - def test_binding_by_relation(self): - fake_script(self, 'network-get', - '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out)) - binding_name = 'db0' - expected_calls = [ - ['relation-ids', 'db0', '--format=json'], - # The two invocations below are due to the get_relation call. - ['relation-list', '-r', '4', '--format=json'], - ['network-get', 'db0', '-r', '4', '--format=json'], - ] - binding = self.model.get_binding(self.model.get_relation(binding_name)) - self._check_binding_data(binding_name, binding) - self.assertEqual(fake_script_calls(self, clear=True), expected_calls) - - -class TestModelBackend(unittest.TestCase): - - def setUp(self): - os.environ['JUJU_UNIT_NAME'] = 'myapp/0' - self.addCleanup(os.environ.pop, 'JUJU_UNIT_NAME') - - self._backend = None - - @property - def backend(self): - if self._backend is None: - self._backend = ops.model.ModelBackend() - return self._backend - - def test_relation_tool_errors(self): - err_msg = 'ERROR invalid value "$2" for option -r: relation not found' - - test_cases = [( - lambda: fake_script(self, 'relation-list', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.relation_list(3), - ops.model.ModelError, - [['relation-list', '-r', '3', '--format=json']], - ), ( - lambda: fake_script(self, 'relation-list', 'echo {} >&2 ; exit 2'.format(err_msg)), - lambda: self.backend.relation_list(3), - ops.model.RelationNotFoundError, - [['relation-list', '-r', '3', '--format=json']], - ), ( - lambda: fake_script(self, 'relation-set', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.relation_set(3, 'foo', 'bar', is_app=False), - ops.model.ModelError, - [['relation-set', '-r', '3', 'foo=bar', '--app=False']], - ), ( - lambda: fake_script(self, 'relation-set', 'echo {} >&2 ; exit 2'.format(err_msg)), - lambda: self.backend.relation_set(3, 'foo', 'bar', is_app=False), - ops.model.RelationNotFoundError, - [['relation-set', '-r', '3', 'foo=bar', '--app=False']], - ), ( - lambda: fake_script(self, 'relation-get', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.relation_get(3, 'remote/0', is_app=False), - ops.model.ModelError, - [['relation-get', '-r', '3', '-', 'remote/0', '--app=False', '--format=json']], - ), ( - lambda: fake_script(self, 'relation-get', 'echo {} >&2 ; exit 2'.format(err_msg)), - lambda: self.backend.relation_get(3, 'remote/0', is_app=False), - ops.model.RelationNotFoundError, - [['relation-get', '-r', '3', '-', 'remote/0', '--app=False', '--format=json']], - )] - - for do_fake, run, exception, calls in test_cases: - do_fake() - with self.assertRaises(exception): - run() - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_status_is_app_forced_kwargs(self): - fake_script(self, 'status-get', 'exit 1') - fake_script(self, 'status-set', 'exit 1') - - test_cases = ( - lambda: self.backend.status_get(False), - lambda: self.backend.status_get(True), - lambda: self.backend.status_set('active', '', False), - lambda: self.backend.status_set('active', '', True), - ) - - for case in test_cases: - with self.assertRaises(TypeError): - case() - - def test_storage_tool_errors(self): - test_cases = [( - lambda: fake_script(self, 'storage-list', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_list('foobar'), - ops.model.ModelError, - [['storage-list', 'foobar', '--format=json']], - ), ( - lambda: fake_script(self, 'storage-get', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_get('foobar', 'someattr'), - ops.model.ModelError, - [['storage-get', '-s', 'foobar', 'someattr', '--format=json']], - ), ( - lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_add('foobar', count=2), - ops.model.ModelError, - [['storage-add', 'foobar=2']], - ), ( - lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_add('foobar', count=object), - TypeError, - [], - ), ( - lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_add('foobar', count=True), - TypeError, - [], - )] - for do_fake, run, exception, calls in test_cases: - do_fake() - with self.assertRaises(exception): - run() - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_network_get(self): - network_get_out = '''{ - "bind-addresses": [ - { - "mac-address": "", - "interface-name": "", - "addresses": [ - { - "hostname": "", - "value": "192.0.2.2", - "cidr": "" - } - ] - } - ], - "egress-subnets": [ - "192.0.2.2/32" - ], - "ingress-addresses": [ - "192.0.2.2" - ] -}''' - fake_script(self, 'network-get', - '''[ "$1" = deadbeef ] && echo '{}' || exit 1'''.format(network_get_out)) - network_info = self.backend.network_get('deadbeef') - self.assertEqual(network_info, json.loads(network_get_out)) - self.assertEqual(fake_script_calls(self, clear=True), - [['network-get', 'deadbeef', '--format=json']]) - - network_info = self.backend.network_get('deadbeef', 1) - self.assertEqual(network_info, json.loads(network_get_out)) - self.assertEqual(fake_script_calls(self, clear=True), - [['network-get', 'deadbeef', '-r', '1', '--format=json']]) - - def test_network_get_errors(self): - err_no_endpoint = 'ERROR no network config found for binding "$2"' - err_no_rel = 'ERROR invalid value "$3" for option -r: relation not found' - - test_cases = [( - lambda: fake_script(self, 'network-get', - 'echo {} >&2 ; exit 1'.format(err_no_endpoint)), - lambda: self.backend.network_get("deadbeef"), - ops.model.ModelError, - [['network-get', 'deadbeef', '--format=json']], - ), ( - lambda: fake_script(self, 'network-get', 'echo {} >&2 ; exit 2'.format(err_no_rel)), - lambda: self.backend.network_get("deadbeef", 3), - ops.model.RelationNotFoundError, - [['network-get', 'deadbeef', '-r', '3', '--format=json']], - )] - for do_fake, run, exception, calls in test_cases: - do_fake() - with self.assertRaises(exception): - run() - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_get_error(self): - fake_script(self, 'action-get', '') - fake_script(self, 'action-get', 'echo fooerror >&2 ; exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.action_get() - calls = [['action-get', '--format=json']] - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_set_error(self): - fake_script(self, 'action-get', '') - fake_script(self, 'action-set', 'echo fooerror >&2 ; exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.action_set(OrderedDict([('foo', 'bar'), ('dead', 'beef cafe')])) - calls = [["action-set", "foo=bar", "dead=beef cafe"]] - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_log_error(self): - fake_script(self, 'action-get', '') - fake_script(self, 'action-log', 'echo fooerror >&2 ; exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.action_log('log-message') - calls = [["action-log", "log-message"]] - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_get(self): - fake_script(self, 'action-get', """echo '{"foo-name": "bar", "silent": false}'""") - params = self.backend.action_get() - self.assertEqual(params['foo-name'], 'bar') - self.assertEqual(params['silent'], False) - self.assertEqual(fake_script_calls(self), [['action-get', '--format=json']]) - - def test_action_set(self): - fake_script(self, 'action-get', 'exit 1') - fake_script(self, 'action-set', 'exit 0') - self.backend.action_set(OrderedDict([('x', 'dead beef'), ('y', 1)])) - self.assertEqual(fake_script_calls(self), [['action-set', 'x=dead beef', 'y=1']]) - - def test_action_fail(self): - fake_script(self, 'action-get', 'exit 1') - fake_script(self, 'action-fail', 'exit 0') - self.backend.action_fail('error 42') - self.assertEqual(fake_script_calls(self), [['action-fail', 'error 42']]) - - def test_action_log(self): - fake_script(self, 'action-get', 'exit 1') - fake_script(self, 'action-log', 'exit 0') - self.backend.action_log('progress: 42%') - self.assertEqual(fake_script_calls(self), [['action-log', 'progress: 42%']]) - - def test_application_version_set(self): - fake_script(self, 'application-version-set', 'exit 0') - self.backend.application_version_set('1.2b3') - self.assertEqual(fake_script_calls(self), [['application-version-set', '--', '1.2b3']]) - - def test_application_version_set_invalid(self): - fake_script(self, 'application-version-set', 'exit 0') - with self.assertRaises(TypeError): - self.backend.application_version_set(2) - with self.assertRaises(TypeError): - self.backend.application_version_set() - self.assertEqual(fake_script_calls(self), []) - - def test_juju_log(self): - fake_script(self, 'juju-log', 'exit 0') - self.backend.juju_log('WARNING', 'foo') - self.assertEqual(fake_script_calls(self, clear=True), - [['juju-log', '--log-level', 'WARNING', 'foo']]) - - with self.assertRaises(TypeError): - self.backend.juju_log('DEBUG') - self.assertEqual(fake_script_calls(self, clear=True), []) - - fake_script(self, 'juju-log', 'exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.juju_log('BAR', 'foo') - self.assertEqual(fake_script_calls(self, clear=True), - [['juju-log', '--log-level', 'BAR', 'foo']]) - - def test_valid_metrics(self): - fake_script(self, 'add-metric', 'exit 0') - test_cases = [( - OrderedDict([('foo', 42), ('b-ar', 4.5), ('ba_-z', 4.5), ('a', 1)]), - OrderedDict([('de', 'ad'), ('be', 'ef_ -')]), - [['add-metric', '--labels', 'de=ad,be=ef_ -', - 'foo=42', 'b-ar=4.5', 'ba_-z=4.5', 'a=1']] - ), ( - OrderedDict([('foo1', 0), ('b2r', 4.5)]), - OrderedDict([('d3', 'aд'), ('b33f', '3_ -')]), - [['add-metric', '--labels', 'd3=aд,b33f=3_ -', 'foo1=0', 'b2r=4.5']], - )] - for metrics, labels, expected_calls in test_cases: - self.backend.add_metrics(metrics, labels) - self.assertEqual(fake_script_calls(self, clear=True), expected_calls) - - def test_invalid_metric_names(self): - invalid_inputs = [ - ({'': 4.2}, {}), - ({'1': 4.2}, {}), - ({'1': -4.2}, {}), - ({'123': 4.2}, {}), - ({'1foo': 4.2}, {}), - ({'-foo': 4.2}, {}), - ({'_foo': 4.2}, {}), - ({'foo-': 4.2}, {}), - ({'foo_': 4.2}, {}), - ({'a-': 4.2}, {}), - ({'a_': 4.2}, {}), - ({'BAЯ': 4.2}, {}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - def test_invalid_metric_values(self): - invalid_inputs = [ - ({'a': float('+inf')}, {}), - ({'a': float('-inf')}, {}), - ({'a': float('nan')}, {}), - ({'foo': 'bar'}, {}), - ({'foo': '1O'}, {}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - def test_invalid_metric_labels(self): - invalid_inputs = [ - ({'foo': 4.2}, {'': 'baz'}), - ({'foo': 4.2}, {',bar': 'baz'}), - ({'foo': 4.2}, {'b=a=r': 'baz'}), - ({'foo': 4.2}, {'BAЯ': 'baz'}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - def test_invalid_metric_label_values(self): - invalid_inputs = [ - ({'foo': 4.2}, {'bar': ''}), - ({'foo': 4.2}, {'bar': 'b,az'}), - ({'foo': 4.2}, {'bar': 'b=az'}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - -class TestLazyMapping(unittest.TestCase): - - def test_invalidate(self): - loaded = [] - - class MyLazyMap(ops.model.LazyMapping): - def _load(self): - loaded.append(1) - return {'foo': 'bar'} - - map = MyLazyMap() - self.assertEqual(map['foo'], 'bar') - self.assertEqual(loaded, [1]) - self.assertEqual(map['foo'], 'bar') - self.assertEqual(loaded, [1]) - map._invalidate() - self.assertEqual(map['foo'], 'bar') - self.assertEqual(loaded, [1, 1]) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py deleted file mode 100644 index 1645e5a2..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py +++ /dev/null @@ -1,756 +0,0 @@ -#!/usr/bin/python3 -# Copyright 2019 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. - -import importlib -import pathlib -import shutil -import sys -import tempfile -import textwrap -import unittest - -from ops.charm import ( - CharmBase, - RelationEvent, -) -from ops.framework import ( - Object, -) -from ops.model import ( - ModelError, - RelationNotFoundError, -) -from ops.testing import Harness - - -class TestHarness(unittest.TestCase): - - def test_add_relation(self): - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - self.assertIsInstance(rel_id, int) - backend = harness._backend - self.assertEqual(backend.relation_ids('db'), [rel_id]) - self.assertEqual(backend.relation_list(rel_id), []) - # Make sure the initial data bags for our app and unit are empty. - self.assertEqual(backend.relation_get(rel_id, 'test-app', is_app=True), {}) - self.assertEqual(backend.relation_get(rel_id, 'test-app/0', is_app=False), {}) - - def test_add_relation_and_unit(self): - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - self.assertIsInstance(rel_id, int) - harness.add_relation_unit(rel_id, 'postgresql/0') - harness.update_relation_data(rel_id, 'postgresql/0', {'foo': 'bar'}) - backend = harness._backend - self.assertEqual(backend.relation_ids('db'), [rel_id]) - self.assertEqual(backend.relation_list(rel_id), ['postgresql/0']) - self.assertEqual( - backend.relation_get(rel_id, 'postgresql/0', is_app=False), - {'foo': 'bar'}) - - def test_add_relation_with_remote_app_data(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - remote_app = 'postgresql' - rel_id = harness.add_relation('db', remote_app) - harness.update_relation_data(rel_id, 'postgresql', {'app': 'data'}) - self.assertIsInstance(rel_id, int) - backend = harness._backend - self.assertEqual([rel_id], backend.relation_ids('db')) - self.assertEqual({'app': 'data'}, backend.relation_get(rel_id, remote_app, is_app=True)) - - def test_add_relation_with_our_initial_data(self): - - class InitialDataTester(CharmBase): - """Record the relation-changed events.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - self.observed_events = [] - self.framework.observe(self.on.db_relation_changed, self._on_db_relation_changed) - - def _on_db_relation_changed(self, event): - self.observed_events.append(event) - - # language=YAML - harness = Harness(InitialDataTester, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - harness.update_relation_data(rel_id, 'test-app', {'k': 'v1'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.1'}) - backend = harness._backend - self.assertEqual({'k': 'v1'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - - harness.begin() - self.assertEqual({'k': 'v1'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - # Make sure no relation-changed events are emitted for our own data bags. - self.assertEqual([], harness.charm.observed_events) - - # A remote unit can still update our app relation data bag since our unit is not a leader. - harness.update_relation_data(rel_id, 'test-app', {'k': 'v2'}) - # And we get an event - self.assertEqual([], harness.charm.observed_events) - # We can also update our own relation data, even if it is a bit 'cheaty' - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.2'}) - # But no event happens - - # Updating our data app relation data bag and our unit data bag does not generate events. - harness.set_leader(True) - harness.update_relation_data(rel_id, 'test-app', {'k': 'v3'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.2'}) - self.assertEqual([], harness.charm.observed_events) - - def test_add_peer_relation_with_initial_data_leader(self): - - class InitialDataTester(CharmBase): - """Record the relation-changed events.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - self.observed_events = [] - self.framework.observe(self.on.cluster_relation_changed, - self._on_cluster_relation_changed) - - def _on_cluster_relation_changed(self, event): - self.observed_events.append(event) - - # language=YAML - harness = Harness(InitialDataTester, meta=''' - name: test-app - peers: - cluster: - interface: cluster - ''') - # TODO: dmitriis 2020-04-07 test a minion unit and initial peer relation app data - # events when the harness begins to emit events for initial data. - harness.set_leader(is_leader=True) - rel_id = harness.add_relation('cluster', 'test-app') - harness.update_relation_data(rel_id, 'test-app', {'k': 'v'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.1'}) - backend = harness._backend - self.assertEqual({'k': 'v'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - - harness.begin() - self.assertEqual({'k': 'v'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - # Make sure no relation-changed events are emitted for our own data bags. - self.assertEqual([], harness.charm.observed_events) - - # Updating our app relation data bag and our unit data bag does not trigger events - harness.update_relation_data(rel_id, 'test-app', {'k': 'v2'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.2'}) - self.assertEqual([], harness.charm.observed_events) - - # If our unit becomes a minion, updating app relation data indirectly becomes possible - # and our charm gets notifications. - harness.set_leader(False) - harness.update_relation_data(rel_id, 'test-app', {'k': 'v3'}) - self.assertEqual({'k': 'v3'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertTrue(len(harness.charm.observed_events), 1) - self.assertIsInstance(harness.charm.observed_events[0], RelationEvent) - - def test_relation_events(self): - harness = Harness(RelationEventCharm, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.charm.observe_relation_events('db') - self.assertEqual(harness.charm.get_changes(), []) - rel_id = harness.add_relation('db', 'postgresql') - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-created', - 'data': { - 'app': 'postgresql', - 'unit': None, - 'relation_id': rel_id, - }}]) - harness.add_relation_unit(rel_id, 'postgresql/0') - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-joined', - 'data': { - 'app': 'postgresql', - 'unit': 'postgresql/0', - 'relation_id': rel_id, - }}]) - harness.update_relation_data(rel_id, 'postgresql', {'foo': 'bar'}) - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-changed', - 'data': { - 'app': 'postgresql', - 'unit': None, - 'relation_id': rel_id, - }}]) - harness.update_relation_data(rel_id, 'postgresql/0', {'baz': 'bing'}) - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-changed', - 'data': { - 'app': 'postgresql', - 'unit': 'postgresql/0', - 'relation_id': rel_id, - }}]) - - def test_get_relation_data(self): - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - harness.update_relation_data(rel_id, 'postgresql', {'remote': 'data'}) - self.assertEqual(harness.get_relation_data(rel_id, 'test-app'), {}) - self.assertEqual(harness.get_relation_data(rel_id, 'test-app/0'), {}) - self.assertEqual(harness.get_relation_data(rel_id, 'test-app/1'), None) - self.assertEqual(harness.get_relation_data(rel_id, 'postgresql'), {'remote': 'data'}) - with self.assertRaises(KeyError): - # unknown relation id - harness.get_relation_data(99, 'postgresql') - - def test_create_harness_twice(self): - metadata = ''' - name: my-charm - requires: - db: - interface: pgsql - ''' - harness1 = Harness(CharmBase, meta=metadata) - harness2 = Harness(CharmBase, meta=metadata) - harness1.begin() - harness2.begin() - helper1 = DBRelationChangedHelper(harness1.charm, "helper1") - helper2 = DBRelationChangedHelper(harness2.charm, "helper2") - rel_id = harness2.add_relation('db', 'postgresql') - harness2.update_relation_data(rel_id, 'postgresql', {'key': 'value'}) - # Helper2 should see the event triggered by harness2, but helper1 should see no events. - self.assertEqual(helper1.changes, []) - self.assertEqual(helper2.changes, [(rel_id, 'postgresql')]) - - def test_begin_twice(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - harness.begin() - with self.assertRaises(RuntimeError): - harness.begin() - - def test_update_relation_exposes_new_data(self): - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - viewer = RelationChangedViewer(harness.charm, 'db') - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - harness.update_relation_data(rel_id, 'postgresql/0', {'initial': 'data'}) - self.assertEqual(viewer.changes, [{'initial': 'data'}]) - harness.update_relation_data(rel_id, 'postgresql/0', {'new': 'value'}) - self.assertEqual(viewer.changes, [{'initial': 'data'}, - {'initial': 'data', 'new': 'value'}]) - - def test_update_relation_no_local_unit_change_event(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - rel = harness.charm.model.get_relation('db') - rel.data[harness.charm.model.unit]['key'] = 'value' - # there should be no event for updating our own data - harness.update_relation_data(rel_id, 'my-charm/0', {'new': 'other'}) - # but the data will be updated. - self.assertEqual({'key': 'value', 'new': 'other'}, rel.data[harness.charm.model.unit]) - - rel.data[harness.charm.model.unit]['new'] = 'value' - # Our unit data bag got updated. - self.assertEqual(rel.data[harness.charm.model.unit]['new'], 'value') - # But there were no changed events registered by our unit. - self.assertEqual([], helper.changes) - - def test_update_peer_relation_no_local_unit_change_event(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: postgresql - peers: - db: - interface: pgsql - ''') - harness.begin() - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - - rel = harness.charm.model.get_relation('db') - rel.data[harness.charm.model.unit]['key'] = 'value' - rel = harness.charm.model.get_relation('db') - harness.update_relation_data(rel_id, 'postgresql/0', {'key': 'v1'}) - self.assertEqual({'key': 'v1'}, rel.data[harness.charm.model.unit]) - # Make sure there was no event - self.assertEqual([], helper.changes) - - rel.data[harness.charm.model.unit]['key'] = 'v2' - # Our unit data bag got updated. - self.assertEqual({'key': 'v2'}, dict(rel.data[harness.charm.model.unit])) - # But there were no changed events registered by our unit. - self.assertEqual([], helper.changes) - - # Same for when our unit is a leader. - harness.set_leader(is_leader=True) - harness.update_relation_data(rel_id, 'postgresql/0', {'key': 'v3'}) - self.assertEqual({'key': 'v3'}, dict(rel.data[harness.charm.model.unit])) - self.assertEqual([], helper.changes) - - rel.data[harness.charm.model.unit]['key'] = 'v4' - self.assertEqual(rel.data[harness.charm.model.unit]['key'], 'v4') - self.assertEqual([], helper.changes) - - def test_update_peer_relation_app_data(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: postgresql - peers: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(is_leader=True) - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - rel = harness.charm.model.get_relation('db') - rel.data[harness.charm.app]['key'] = 'value' - harness.update_relation_data(rel_id, 'postgresql', {'key': 'v1'}) - self.assertEqual({'key': 'v1'}, rel.data[harness.charm.app]) - self.assertEqual([], helper.changes) - - rel.data[harness.charm.app]['key'] = 'v2' - # Our unit data bag got updated. - self.assertEqual(rel.data[harness.charm.model.app]['key'], 'v2') - # But there were no changed events registered by our unit. - self.assertEqual([], helper.changes) - - # If our unit is not a leader unit we get an update about peer app relation data changes. - harness.set_leader(is_leader=False) - harness.update_relation_data(rel_id, 'postgresql', {'k2': 'v2'}) - self.assertEqual(rel.data[harness.charm.model.app]['k2'], 'v2') - self.assertEqual(helper.changes, [(0, 'postgresql')]) - - def test_update_relation_no_local_app_change_event(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(False) - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - # TODO: remove this as soon as https://github.com/canonical/operator/issues/175 is fixed. - harness.add_relation_unit(rel_id, 'postgresql/0') - self.assertEqual(helper.changes, []) - - harness.update_relation_data(rel_id, 'my-charm', {'new': 'value'}) - rel = harness.charm.model.get_relation('db') - self.assertEqual(rel.data[harness.charm.app]['new'], 'value') - - # Our app data bag got updated. - self.assertEqual(rel.data[harness.charm.model.app]['new'], 'value') - # But there were no changed events registered by our unit. - self.assertEqual(helper.changes, []) - - def test_update_relation_remove_data(self): - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - viewer = RelationChangedViewer(harness.charm, 'db') - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - harness.update_relation_data(rel_id, 'postgresql/0', {'initial': 'data'}) - harness.update_relation_data(rel_id, 'postgresql/0', {'initial': ''}) - self.assertEqual(viewer.changes, [{'initial': 'data'}, {}]) - - def test_update_config(self): - harness = Harness(RecordingCharm) - harness.begin() - harness.update_config(key_values={'a': 'foo', 'b': 2}) - self.assertEqual( - harness.charm.changes, - [{'name': 'config', 'data': {'a': 'foo', 'b': 2}}]) - harness.update_config(key_values={'b': 3}) - self.assertEqual( - harness.charm.changes, - [{'name': 'config', 'data': {'a': 'foo', 'b': 2}}, - {'name': 'config', 'data': {'a': 'foo', 'b': 3}}]) - # you can set config values to the empty string, you can use unset to actually remove items - harness.update_config(key_values={'a': ''}, unset=set('b')) - self.assertEqual( - harness.charm.changes, - [{'name': 'config', 'data': {'a': 'foo', 'b': 2}}, - {'name': 'config', 'data': {'a': 'foo', 'b': 3}}, - {'name': 'config', 'data': {'a': ''}}, - ]) - - def test_set_leader(self): - harness = Harness(RecordingCharm) - # No event happens here - harness.set_leader(False) - harness.begin() - self.assertFalse(harness.charm.model.unit.is_leader()) - harness.set_leader(True) - self.assertEqual(harness.charm.get_changes(reset=True), [{'name': 'leader-elected'}]) - self.assertTrue(harness.charm.model.unit.is_leader()) - harness.set_leader(False) - self.assertFalse(harness.charm.model.unit.is_leader()) - # No hook event when you lose leadership. - # TODO: verify if Juju always triggers `leader-settings-changed` if you - # lose leadership. - self.assertEqual(harness.charm.get_changes(reset=True), []) - harness.disable_hooks() - harness.set_leader(True) - # No hook event if you have disabled them - self.assertEqual(harness.charm.get_changes(reset=True), []) - - def test_relation_set_app_not_leader(self): - harness = Harness(RecordingCharm, meta=''' - name: test-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(False) - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - rel = harness.charm.model.get_relation('db') - with self.assertRaises(ModelError): - rel.data[harness.charm.app]['foo'] = 'bar' - # The data has not actually been changed - self.assertEqual(harness.get_relation_data(rel_id, 'test-charm'), {}) - harness.set_leader(True) - rel.data[harness.charm.app]['foo'] = 'bar' - self.assertEqual(harness.get_relation_data(rel_id, 'test-charm'), {'foo': 'bar'}) - - def test_hooks_enabled_and_disabled(self): - harness = Harness(RecordingCharm, meta=''' - name: test-charm - ''') - # Before begin() there are no events. - harness.update_config({'value': 'first'}) - # By default, after begin the charm is set up to receive events. - harness.begin() - harness.update_config({'value': 'second'}) - self.assertEqual( - harness.charm.get_changes(reset=True), - [{'name': 'config', 'data': {'value': 'second'}}]) - # Once disabled, we won't see config-changed when we make an update - harness.disable_hooks() - harness.update_config({'third': '3'}) - self.assertEqual(harness.charm.get_changes(reset=True), []) - harness.enable_hooks() - harness.update_config({'value': 'fourth'}) - self.assertEqual( - harness.charm.get_changes(reset=True), - [{'name': 'config', 'data': {'value': 'fourth', 'third': '3'}}]) - - def test_metadata_from_directory(self): - tmp = pathlib.Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(tmp)) - metadata_filename = tmp / 'metadata.yaml' - with metadata_filename.open('wt') as metadata: - metadata.write(textwrap.dedent(''' - name: my-charm - requires: - db: - interface: pgsql - ''')) - harness = self._get_dummy_charm_harness(tmp) - harness.begin() - self.assertEqual(list(harness.model.relations), ['db']) - # The charm_dir also gets set - self.assertEqual(harness.framework.charm_dir, tmp) - - def test_actions_from_directory(self): - tmp = pathlib.Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(tmp)) - actions_filename = tmp / 'actions.yaml' - with actions_filename.open('wt') as actions: - actions.write(textwrap.dedent(''' - test: - description: a dummy action - ''')) - harness = self._get_dummy_charm_harness(tmp) - harness.begin() - self.assertEqual(list(harness.framework.meta.actions), ['test']) - # The charm_dir also gets set - self.assertEqual(harness.framework.charm_dir, tmp) - - def _get_dummy_charm_harness(self, tmp): - self._write_dummy_charm(tmp) - charm_mod = importlib.import_module('charm') - harness = Harness(charm_mod.MyTestingCharm) - return harness - - def _write_dummy_charm(self, tmp): - srcdir = tmp / 'src' - srcdir.mkdir(0o755) - charm_filename = srcdir / 'charm.py' - with charm_filename.open('wt') as charmpy: - # language=Python - charmpy.write(textwrap.dedent(''' - from ops.charm import CharmBase - class MyTestingCharm(CharmBase): - pass - ''')) - orig = sys.path[:] - sys.path.append(str(srcdir)) - - def cleanup(): - sys.path = orig - sys.modules.pop('charm') - - self.addCleanup(cleanup) - - def test_actions_passed_in(self): - harness = Harness( - CharmBase, - meta=''' - name: test-app - ''', - actions=''' - test-action: - description: a dummy test action - ''') - self.assertEqual(list(harness.framework.meta.actions), ['test-action']) - - def test_relation_set_deletes(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(False) - rel_id = harness.add_relation('db', 'postgresql') - harness.update_relation_data(rel_id, 'test-charm/0', {'foo': 'bar'}) - harness.add_relation_unit(rel_id, 'postgresql/0') - rel = harness.charm.model.get_relation('db', rel_id) - del rel.data[harness.charm.model.unit]['foo'] - self.assertEqual({}, harness.get_relation_data(rel_id, 'test-charm/0')) - - def test_set_workload_version(self): - harness = Harness(CharmBase, meta=''' - name: app - ''') - harness.begin() - self.assertIsNone(harness.get_workload_version()) - harness.charm.model.unit.set_workload_version('1.2.3') - self.assertEqual(harness.get_workload_version(), '1.2.3') - - -class DBRelationChangedHelper(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.changes = [] - parent.framework.observe(parent.on.db_relation_changed, self.on_relation_changed) - - def on_relation_changed(self, event): - if event.unit is not None: - self.changes.append((event.relation.id, event.unit.name)) - else: - self.changes.append((event.relation.id, event.app.name)) - - -class RelationChangedViewer(Object): - """Track relation_changed events and saves the data seen in the relation bucket.""" - - def __init__(self, charm, relation_name): - super().__init__(charm, relation_name) - self.changes = [] - charm.framework.observe(charm.on[relation_name].relation_changed, self.on_relation_changed) - - def on_relation_changed(self, event): - if event.unit is not None: - data = event.relation.data[event.unit] - else: - data = event.relation.data[event.app] - self.changes.append(dict(data)) - - -class RecordingCharm(CharmBase): - """Record the events that we see, and any associated data.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - self.changes = [] - self.framework.observe(self.on.config_changed, self.on_config_changed) - self.framework.observe(self.on.leader_elected, self.on_leader_elected) - - def get_changes(self, reset=True): - changes = self.changes - if reset: - self.changes = [] - return changes - - def on_config_changed(self, _): - self.changes.append(dict(name='config', data=dict(self.framework.model.config))) - - def on_leader_elected(self, _): - self.changes.append(dict(name='leader-elected')) - - -class RelationEventCharm(RecordingCharm): - """Record events related to relation lifecycles.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - - def observe_relation_events(self, relation_name): - self.framework.observe(self.on[relation_name].relation_created, self._on_relation_created) - self.framework.observe(self.on[relation_name].relation_joined, self._on_relation_joined) - self.framework.observe(self.on[relation_name].relation_changed, self._on_relation_changed) - self.framework.observe(self.on[relation_name].relation_departed, - self._on_relation_departed) - self.framework.observe(self.on[relation_name].relation_broken, self._on_relation_broken) - - def _on_relation_created(self, event): - self._observe_relation_event('relation-created', event) - - def _on_relation_joined(self, event): - self._observe_relation_event('relation-joined', event) - - def _on_relation_changed(self, event): - self._observe_relation_event('relation-changed', event) - - def _on_relation_departed(self, event): - self._observe_relation_event('relation-departed', event) - - def _on_relation_broken(self, event): - self._observe_relation_event('relation-broken', event) - - def _observe_relation_event(self, event_name, event): - unit_name = None - if event.unit is not None: - unit_name = event.unit.name - app_name = None - if event.app is not None: - app_name = event.app.name - self.changes.append( - dict(name=event_name, - data=dict(app=app_name, unit=unit_name, relation_id=event.relation.id))) - - -class TestTestingModelBackend(unittest.TestCase): - - def test_status_set_get_unit(self): - harness = Harness(CharmBase, meta=''' - name: app - ''') - backend = harness._backend - backend.status_set('blocked', 'message', is_app=False) - self.assertEqual(backend.status_get(is_app=False), ('blocked', 'message')) - self.assertEqual(backend.status_get(is_app=True), None) - - def test_status_set_get_app(self): - harness = Harness(CharmBase, meta=''' - name: app - ''') - backend = harness._backend - backend.status_set('blocked', 'message', is_app=True) - self.assertEqual(backend.status_get(is_app=True), ('blocked', 'message')) - self.assertEqual(backend.status_get(is_app=False), None) - - def test_relation_ids_unknown_relation(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - provides: - db: - interface: mydb - ''') - backend = harness._backend - # With no relations added, we just get an empty list for the interface - self.assertEqual(backend.relation_ids('db'), []) - # But an unknown interface raises a ModelError - with self.assertRaises(ModelError): - backend.relation_ids('unknown') - - def test_relation_get_unknown_relation_id(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - ''') - backend = harness._backend - with self.assertRaises(RelationNotFoundError): - backend.relation_get(1234, 'unit/0', False) - - def test_relation_list_unknown_relation_id(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - ''') - backend = harness._backend - with self.assertRaises(RelationNotFoundError): - backend.relation_list(1234) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/requirements.txt b/magma/squid_cnf/charms/squid/requirements.txt new file mode 100644 index 00000000..4da6f5fe --- /dev/null +++ b/magma/squid_cnf/charms/squid/requirements.txt @@ -0,0 +1,3 @@ +ops +jinja2 +git+https://github.com/juju-solutions/resource-oci-image/@c5778285d332edf3d9a538f9d0c06154b7ec1b0b#egg=oci-image diff --git a/magma/squid_cnf/charms/squid/squid.charm b/magma/squid_cnf/charms/squid/squid.charm new file mode 100644 index 0000000000000000000000000000000000000000..00ca09ed1e2947b3e934e45bf8fd81abefdbbc5a GIT binary patch literal 601730 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 J3ljJK|;-(zu~cdgCl_bRS@)t%dO7sb0s7w3c@ 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 z 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�^`5gF4tT1 z|Kiw%y=IEv9T#t;m#3LUc0GRp467D;B(7-q^!{NxqV(}!Mr`I zeZ^fS>y}6hvbcyl2^`Qp{dLDYk;8#3d*XJN^#&VWmwGhY%3FE*#tkzc-!)#hZ2p<> zN$F40cXs*iV3{%h_o?unpSS+pT=stcS{;e4l^%}@1mkum%!%D9Q4_l_WTnLJ-NnuK zE@T?oSIOA;PqWDX^7Lo7LU*>tgoUduUs$i4vHr-?3X3&M(w5v_z}EbGK~UxQ;}ZD? zJpylrDy?=77MNTAXorQ;-YQ}J*A4dsCM&(+sFT({D_a(`{HX4`UpDp&A|>veT$Jaq zk$a8l@}^$~m!2?P*mYQ@@kaVX*MD()=dsKxzrETc#b%xO{G>G|_Z3V0oBh+J58p2I z;`a3acw*(gpzHOoN;jtL=@ij#c-L}f_t}s?HLL0wb2FT-JU?(GpxG$z{Q5Sq>$5`dcq!jtOnzOZ5wxTHNWb;s-&_?_ zx)z68p6o~xI?^6vv~Tgj^*b%+ME#WAesIl+x%XJwvM=Zw+Bw{@EIX`mXKq}yok+Tu z;j$nh)35JL+@=S`^j(_n8Kw2Dz+uXveZ4=w9$w`!Wq;GgAK$It+*+ihlgjIM(sS=} zx9{<%IwkiTcciZJnQeLDWNyfX9YNl9K30aR>AXKpPv-k8o_TUdrJT`q?td>}&&v`x1Z^;dZDWXCuL5&I;`wBxIC#_I?%oLbDWuBJy(SFgT zACz5#MQogG6sL>SSwuXj53uf)^RihMa$rH)rNun2Dqki}KX`KIVrZk~HW=+=iLHF}Th9?WTT(OjPYW};ktOYDuTiyJRqkX@3e@aE5v zPzy7wKAyhIK{Z=9taspA#=3-S>8i7jXIeUDPCU0h!qwGqqSVpPuj@8S}u=dG{ zm>1vox1Qub_CUV&;Cju@wM#C?zyD#NbnL#5%da!XH@jc2Sbw}%x$DXFi!zIfr%BkuWdyCr6}!=;^YH%kC2Mc$d(Qi`?aJ{T zcX{?*zyAFzb0+VJ&}sK3?F-(+oqNrool${h=k~`B{CQ3a957TD5Lx8#Tj-0s2iL1uack7Z1QnMU1uXh&*3ACCzds>)M|*qp+igekLpK=R zb7J`Ho@|`WFkis%NN&02L7{ndnhlx2p2Yd$0ZwV-`ylQK8 z@sVP2q+k4g=QEcX8U2b{gXIpsxu5h&`qF_#>dA4XZ-1vvbnd_W#=@@E{C&d3k8yFK zlXkfAlv-#%e-gQ~yh>)yqj0&jsrzR5y#3zZF8gNU{gxC@$%v&@e&?sIEYr{sQI_fB zD3hphf42R%z_i~+_LuJ*pTIbiX^qj}GyAF(9+rQ2bB*%`f7FbFzqwO<<}tj;N?5bc z?WkyBbX zRk2?F-_MRI?qNGFOT89baq-T=Z%%7=?9E}#Qx2?uu_{5UOktwOinvME>%5Mo*q%N2 zx-kArG~4YvGrldi`nJ(mU;COy-^tHvF&n|z|zTR8aV7@=mrS9^aV=iabTQz$yESg*) zcBkCn&t)|Z?q8Y;a$Se^GJmK#9)e-`T2&6D45`0Vk0i3e@Jm9DFbPmca%;rb_YdZ730 z|5`-#uEyjIs32G!^Xl^a+YrBu9-T)81oN%YEUjpl=4JgYV_Nr*%U zrasQDR({2>YmcGM7v@v}ri!*`yC$CYJoBW>9?ySgAD#1TW13@z>i&wg-Uul)6ucfY$F;Puy#$??~PLCgL z^gaGEA!Ot2L-&K3*;;H1m>mtd|D*>q-H?995~sP=kezvA<&M|k29?uI60E*9@m0;t zyJ7SHQjzPv$jV9b-~PM%{4-VC?@=XnLEBln)ye#Zq0a{^UT5Kkhf590M1-%LlDPLL zHF(B@jf{t1f91KV-1bXwwu-3W3>W^6)0{V}Pu7@hc=X0&yX=#{e>SzY-4@Bc`}&_YL3v$2k8~$WoH|f}xGygcW{~N271T<|o+rj9Y)^Jbd z?Zo-+dtHyHm0eSuThj5sY@*0Vzm+9X?735#@?Pp?IBEvu_$z)57ZKa)q_};-&;S0l zv#!5BrE_)O1j7a4fkj+VjBna^oXd_${hMyF7P~*(C`gpE@*)w4QK$Ps(PMX>Mi7KPuraQyF~t#B4tU+sO_Bos2VC|J@LNd-o4h60rw~VSQxjP+2cu}n}o5mz5THdFDBlvJo374wrh1?>Z4#$6o2tKEa}xo+ZI|{-0G^x9fnUtGNg5U!4v3vwY2~H9AMiPikL0&UXCO)sGM284siZ-n(m$;QRGQkNz%S zzdmpMz5UJc_FbRL>qYDLRei70P?^BlHc|e%=p%lQG!LiF(`tE3z6eB2=?U07ZFA1V zvk7rWize$WjhH5%5_+KINL1MBHOE@lFz&TnoCpfOuL%QbfB*cbjhcV5~rwKGcDc;@}xrag=5-(Cu>+p^-6Xo1hg6aBmg1Ygaq z+T_Kp;Bs{BhlAU^uJ1Y=SMfsiL-yfMW1js<=l$Hm z*yi56SXtrKZ&M+Yv;V99ed9H9i(RMkhC{(;o~;+7{iVuVOE{DK)|fA5U2vZ>wy)tegSi~fbJTjp>yvajOrlrYwUryU#&+ST3B^WsB= zB*i+oV$`;6Sgw114QH;B?4PM-3S6IJ&a8gJoRio1M&*_7HHFuTccS+j_63|2F_$W9vH!TAeICDn@7Xo~%iMiz z4SeG|u4~9Tm^6G@lghlg@vr9D-(JtQOg(l}=72_nr`7!aue0m&?cVab=Eq*+Ju&;& z_C3#=>cjI2lT9)iolP#y_2y)5GWmNTWUZ``Q*)B$>jI^dA$pq^*=N|6f0TTz_RhMZ zddJ*-ueR>azjk2vB_{{Jd+doCc3peDREU=Lww@ghmwL#EdACq7-LV@Ok~hLwQA>|+{w>sdu@3qcc^%>?fLTj zYS70GH{U*vjO*|Cn(B6XKMig_RGuzl;~K$pft zmy;%|h^;H!X|TYwLfJ&9aH~RWbpEv^0&Pj!mD*2Je|nU7x}JZ1Ik}eS5lh=ghxLi| z42F>%Q>F&)GU-;-;+puepj)VkP)2d*P&u-&3HMW zbMM9Qh5h=@^Ihb&pB4`~?#K2aD&_QgWAV1Hb5>f|)?N4UaDFUbyi?$@;i+98cf5Bz zxYqQ`#jUg5vM1k-y2l#*@ZS3`MK_Y(PvqEgefOpbhi_=vFI*be?{WCxiRr@0#*7&W z|N6EDGAz2=xaPyI@G0sE>~`}OI9_&^bYEs5wN1e!qHGeQRhp~Wu}=069|RkM4&-jO z`ezS?nwGqhBu-8sf}hvt2W=x5;iMb@~?tz z(ZY!yO%7cBfk7vj9DDL3GxoXe{mN|rj{OF|?32TqoAy~J@0~6%WnZrCm*d>l+S0r$ z57(=j|NqFQ(<}Y&>igcXBG%nWSGcREZRS}PHGOuL+C*2o+I!BPpUacp-23*=@CJ{w zSkZF(lI3@!^1=?Ec~%>+A^E~O>B#vXU+?jG{_3g3x1wDqXYV?{pWW;8--)8Rn~kOC zZBXdqJ92V=>#j5Jq$UVmPxu?6k~HNY({iixKZ>S26Ps$Km24H8xpGp(<=3&E+xSdO zA90APciA47Iwb5q`Dw~U+a(G5ha|-!E;~proM<~MV|V(b9Y3thq!iyx*xN0oeK_8Q zxBcZV4Z}sA{c8VtmvVxje>`R9%<8``e}8rB@{elH zEuo&zOG6Rc5M~N6zU**Cl=kojXz$^36NvK}^%(pFU=dmO^Taw`6Kn zc>OUsxG~WLyo_sq`e$&n774oNi`(Ai0u$o)S_$!SwrfYWl zin@QFMT2-MYmU2DC^T+W;?!Gp(p#zA-XLJoCXZvuS*CLQHFb`H+1GCzYT#QDaXdLY z*yZ5NGIzley`HRsUF;kT|L5-9Q7zMMbT58-_XK4LiwYN6(c#IJ~n|Qo*j%;c?@V%VLI? zd$YqH1#@1${5z)evTWsnjBj2uZ?kUR#&pWT%rfiVJ?^r1Mm*R2PB>MZT6HRhyXJMW zQYphFi8kX0Gf%vD+GzKLIeCrzrLR$ou8YhtIXd^=iLVm`bf;X8&_8;r;xW&KeKD(? z#om~^K4Y2cQ*Tf(eesrk#h)f*YsOEx%GIJVaWZ>oliC+i&5QOS=QJZ`Ps=}LWmK`Q zVpc<{g5Kt9(z*p_weLL8URwA;!}-)PN9#x4i;vpB@qe7V`~LE0kN&mRnX=E;FRk0D zux}ponO3e~`Q}?QPOs`$U%S^?d-4BZ|BJkipEv8hnEOaQrYAbhF5*q(t5?N!*)B(F zs)W2c_qqRB_~7K66LVsY%NnUPyl+a4JQT2cY23tw47O|cx98{=#QRPy>4;8I+2&lH zd3(waxh-PC9=ZEX*clJSdDX74VYF>#T)9)|m}={8mD5&V9!@#8Ix6UH4eIQtZUah^4QsCzO8Q#e4dQ+Zpf3-D)4X zH{Mwy%E8n5O>#lQ#Lb(UMBUCT-*j`4jJa~=rM8Nz}qhUjNBkr%b&+QM2gi^UND< zqLGGC>lf_hOYv%rHMx=F5ErpsGl4a%PvfG@5IfiD8KNt;>611Uj3~FO>w8@e&2FzN!($x1r{Rp7Db!) za(OI1%oM^X-Lhz+NALejQOQ57`VCmkK7{?=8T0Tst4{V-hT}Kf=ev7mYVo?RGQ5xw zsJkRddx565*H?#Fv9^L6{~I53FH>9Pv`KtQ#nFpd&sQAn*4lK{>)ge8?uPprOywMS z&nVCS+Bo_6!$}L6&u-9Rh&kR-yWkvydDF+)3mvl=f~!Lq=NL4{F5b2?bmo)qEI%Ke ze6n%3F#E!3Z=x!WxU4tt)Y;s8TZk>rwV+}7-yJNu?`K-~KCewm?c9Cy(Wyfki4y52 z7}eG*23=xHZz!LU|4YzqX?@>&<;|;~a7j$N<(lTnE@^yh`kBc$UwU3H3GmD~b*_28 zY3KL;TxQ7^4Y$|uTZb>Rw&4taBXT0D(~pbK($avF)8}(mI@5}oYy1tbMa^I2e`Q{s zzL_XnRPj^mv_T^t&tPJC(uAcUX=l?g;4UUH%e*N|CcC~eXj^G8g zymPO%C$r=>U9h;7Ipe5cm*4tqrfb}1m6aTsY|b^!+o18;aM`i1-`^#=GJXCo+!NGi zc4fw{jx}*nb8^p|cMCXaE;nbg_3{gT#)UZs3Vva)FZkQ11m1YgI5FyirJ=zK%MW7a z315D^TGdcnQn*)UNn4W35JtBtAClgk#Jk;rTLDJQ^ z$+IqbiC;GB;{_g0u8Z%lTM;y|z+Z1~qo31OF&Q6mtF>2_JTB>4vD{OG?JK{=e37KU zf1xcs8`sY+7b#kQ`R#_7pvUto_x_t_Fu%V7D=%RiHZ-uW!L z6>XsOFy61V?f>1^A{$p+tgvgpd{1X{+pIp#%wkQBwG-v<9$9H9@V;c(jjqm$=+~1r zeb?ByRV$I>)bi^_=j5I&f4VI2xiQ=Hj$-9KS)Mv;QzQ}%Rqd7Li-#v3}dl!S@ zLAz(~ZQmN!@iV3Oy*+#X?pyoa!5=%;3N4S}Utt?{;M^K#Lz&YiJFjJbdAZpy(9?I$ zwT9QK+^e;Ll2o!GknQ^D`?R()HeL;UN&$MWhEt<6U(o&m$Mk3rF|2^`GQEc(M z^G0vg$xRoSO7=yr{ay94{gLUPl2-Nqe6o3cmz~b?{#||WPeMzbzjIoy<(0+!HG<_4 zdotgdIKA0(<8Fi5OOeP`dq1V_oc;dfrqd_Gj+f=wLn90C9F503JUd>5wCSmx+anVl zYnoBWaOTjKu3OjTc+$@-))zIES|BLe*AqGYHE&hP-!;!{=WUuF%5Eebup>(D6QAye z$O<1jj`9t2H~ot$3@R$Ppf&&PMW!|}-Q)>>=cP^iyvA+%&4V(lXD^Eh-leWOJ2Ct1 z4|7h#xQU?}svmO}_^#G`rd>C|^4arAsS(N_6z)!0cyZ$;p4DzHnd!APYNGC(r>F4D zb&1&#xnj=T^P9Ik5^Y=cgmeGmo+Y*O_8FZ0e_VvmXWE2!9Mvx>a*q{fo>-p#^cSyY z*OlOT@#>q)(|aPs1=^OHc1;OfXndrpCMH|=;j%EkFt5D}L@)K)zMD}n=W6t+Wm}e8 zc)Oj8ujMmbnbvgckKqcJt6!eVaVhGxeb_7Xd{G`aJ)$N43<^+i|~{ zPVkkyex}u+d*?#k2|F#l^;7ef#Hc^GAK`f3JpIw_4^PfFI3Esm{k`SkE0)PqAFgUL zEqJz!UB%1DVE3J=Rl4bwQ8$YwcwG$;E6PspwYuM7rpNa0gO2US2kPu=T=};~FW)0F zd68bu#|@h87Xky^4GdJQ7hZT#!nEw}0Ui^*lOH~o2p%rIvh@5ejl)Z;!Z&swXV9&? zSv-UDlWT&r*198*6`*( zw+r)ThzaRzRNFs!+YzM# zQ%+qkncEla>U?eK*;|jaCgq--$E=fZ$oSiw)ed1V7f)WXuxrMgKT+$JpU|>X^$#{k zd@ZA&&U7i@;JigwF7rq{*%hsIFn5V|vP;`Wdd9o+`lP?hdehb3d)jwu)!Kfq&MyB^A-~OGi)n(x-ByElf1TdfUS*i+ z=YKHCLyu>{Z1)_4i%%Gt>PGGzEt&jo=0c?>b{W(%$J!QfAvXN%Hk{gCN|Y9 zcw`g#Hjm}Y^21CI!b-JWB|B21TpiSp3Tm6|-E(sJEL(q%ldsk0dhffxTKS{BRFYfy zw#aHL#r0CltE63$G`kE^*&Uwu{B5-1KHvWRsMy2nrcU!R_)4DH*;&885NoxL`?Zm9 z!T+hEU$=`j$xr!~(`tWG?a;x?yg8<_Hx7Cf`dwQTAi2DzJR-vBvG(Vj$SE_#b5?7* z&ecoVENr}IPG`%hZwpnfdJAT+`gUyhiY@c6XPFB`T}#tDa3%G=f3DY&;I)5G7nNrM}v z%?I>z^LBACl`_mQk_pItl6lrs`10J+J?+x1%h}!hR=!)eMIc1-%j54`i~V`xYn$Gz zUZ1z=&Z75uYZAXNosz>7QOF~@VA5?7Mf>J6v;6G78q{|dJ+%Aqb?&q-g(4;=&GLqK zN+IIat=-NFlbYKna!^(sQ=Sd|)^6%Q>{=#6LmbyUy42?w2&r zvdG`n;TjMdep>YE&W`C7j!ZTdPivDtoxk!leO1+|=&gR=zrMGPuhEs3-Yo2|sef_l zPIsmlJ%ia+eN2AaYYXT3DeRiCl9jpEOzZfr-0#LaE<6dpy45P#RF^?J!6SIU45>LT8y@sJ<~Z@8s;6jVl{tI=;4(+I-5G;wp!oJz5St!+h@}IjX_T@ zckkcubw&b9rOzvdD^`g~rTbr9%AdPK)4DtU*sH%bMl1E!wi;YLwedjh7ZVv4*DI`2 z`;?E08qa+wa&>d*fv>;&`=Vadul;c-{0dilR@iFaNMFcEr2R`+&8GeAUp16|JK0vh_KH`sm_GY& z&t&Fjx!XH$t&)*o`@+tB_sh;h*^v!f--rDE_n=d3-Kq-;^aZ&2M5iq zzBO@O-r2BL<@TrMl=DoSU!5+AhS_}Qyjak*UHtGbro8I2+2u>mwMMDf=q9b@y1n?d z$>TpZt#Y-qn!JLOyvyT0FI0{+;*GwyIAdXw+Q$6Q)O8qqOvoX61RMk zF7KRranUB$QoT9nwr^b#6!z;ts`&Ajf8YImoBDd)UIt4YC-wVs_x5S@85)?(4!rTg zBG9-7jsDRz~g-{$|9mEKJ#_+5YT>;8a} zk9u!*-Kshv{QI{{w^iQlk2W(-eMu9(5htUvEOqAUH}~_xpM7&&_1Y_xMd;)9<9w#v z?a42!49?AJJL&h7XNiJW%+-18GUxmd7xv9r$(28y*|hqcjKI%eFSh0Dd#AL2=&dez zz_VUqTk0CgHLoRRTh`w0wO%)6D^J#L?Y)P@XG)f@+|?lW;lIM?g<8`%LqvXuUNt?j z>Jw+_!)2P`3c^38JyQMEzOdS?I5sQf&uT-5)(&QiFAKWYJ$@Je{O&@Nr_SL)ks#ym!8?qh^eM}Vm|{z zclE^Aoeh_|waR#3;Vtit1$-Yrf0`1kwxw=@{Om67tFN3@Q#{yiq@TYlQ~BRbSeSYI?51sRRO<7-K1@hDlTviu-QhmpONN&FDHYNb?96#*zXFZi@xDSPJ}TGbFZYx=KceqFDcrtW$qBq|{mA}aRw*79$Q zwSMR)wO*JKP%ul+(&P*t-3qMBU)?PE&!zZ{DFnYUeP;*0Oc_I{9R6gtc%y}YW2 zYf*vQ56f-)jB_ps-`4EXxaqJw?Z@+{kEfkGpZi#JTY=p*_fqyPJB_O?1nvtw-nMH| zpl`zC?X0^dyuE+F!>(MaERNIBW_8hYpW`Q3+s_>3J10B2?*`8-pS;$%<~=vm#Y)61 z{mR=`eiwYJv@ff6&1(^T?%)(B%Ofw}Y%Du`RMM+P}Q)Bg0BPp$7+a-sthM3Ld%s{-Z>;{*g4E zFQO})pI*A!S}t6A{7XuY^5^GId{#=ncUsPQ^zy6H$SXHPVz+JZGS;7csKPPr#wxZ+ z=g)kfG-YA;O3j)bf%B6We{R+<+rcg66>-aB`jpk{Ely44djB&kNN{tp?%elJE{GR3 zT`h_2c$UB4vx0kh=Cy}2xA0lt)&0h)va~X)RpM2&+r;%UJFmsEBtDl24(v3@tgUUm_wDq^P${j6#|EB2eVei)W5(m`z z52^cg9T1y;H|NTNsjJv8W?PqNIefVKa&@wkf{uOX^5$c9g()(sYt7$T6@ARGXbWER z=G-Oio96aYYq;Gn{?si@bNu3{X(qjIWApzd)#hEt7u^w?!Nczz|9Gvyhb`hx%Tv3U z6m~K^Gp}=e$}qv;_R{Y4S6zNyTC`x%`Q1AVgseYS$!nY_ysh?4ZvS82+Zu%-N49OS zba`hR?0>*iENP!s$V=O$xA_0wmU@xI;rIN(>AP9K^$a$~ci7MQ|MJt_w?DpK{krnu zj?4Bj@%Q%pfBNfD(VusJ-Y)(8`S@z{=|40WJ_YY|UAQ2R^YZsSj|-FZF3x-4|0boh zXhzqs*;`Mp-FNf()_?Ef17G$`t>II9@l5b%c{9fhm6Xqwx>hI^6<^=dvi8j4Je^x9-__4$-b?0Tne)?aPU^ximu+`f<_a9D z@H5`ZC$+ia-mSTB1*V)>k@978MsT^uw^a8_$vbK#&Rdwc+7~5>`Txu}{avm7xQ=Op zvhA|jXII>~etMU(ue-XbUo->X{T1qK{rlZ|+QK%infUcxSfBjMZ}E&zW+vUOJ}tOW zH?XFrvi9%4sHv8UA1pg!MVV3_D1W^C_U-u(pSSbIt=-{a{3WLAv6;r2%!-UzrM6bK ztgpXJ>GA*d|K#%XePaK=+`QGU|A4on_Os!mWZf5w?OGl*ERJ!|=sz&c`r!JLEYtr~ z%+{{BEu~n*d*Q;o^XHRX-tT&;VIa37{q!fPEw_)q<9oE*vewQb_rA~4pb1e6gu2p> z7TvmYTIZ~3W{Gpy5#yFUE#XOd%m1BS@bQk>-P|JDvhz5w{^Yv z$8}e>-Syt^_?N{k$$$9@mu}^YcrPxBQ!lx^U}oJC4qJ%}dn-Hp4f;Y3%y-_Ow?I{K z&SZc4Yxg)kFRnZ~QAmGll-1(qNT2=h4ddP{%X~Thhwc$ zo~S=bTe`*iEqDFD1aC=c?YZaYYA(pQEpqne_Veug4R@k`%}k$eCp+iujkae|8K!aH z|Kw~a<;jWD6OGt<Tz7g+Mvs}X+VjW{ zvR{~)troDm|7Q;HW@Zs#U|`^2*wI%Pcub1_gdPI}0|=w6#VJcID$dN$(<`V94%0Y! zLMM!2kxT2BD|@aiIx^{sNb8m}b3*jiZMw4P(V0IstkJBc&bH3B%%ys02W0J6sVE2( zVPIHn!@wYbywoQ*F%x9=-00Uux80`wJHPzJBr{ecSH~hF&+vzK1X!sMy<<`^k%ssP`_Q}%bqC)QHOr;)8B(DSJa1OGTxr^zU2;s{>C}X?KAIi#d7S_5!s_{ z`e~Q$C8M*`gA>0jx^v2jajJ@G>cn%aH>qkImwa&s4iO*kc(@BM+_8=iV6>9c$BKP-Vg- zSK27$?&tO0^zv!d4G;EZJ^q&(7CJNS>-MaDnk789*Uo?Qs(#w;UU#M|O|y*_yDq$* zqzhdTeDXjUl z#l~oXjHue@1QRL6$bbtgC#UWRd752iHt)b|7hRVncB?pC4UgHUskC)k{PNe{^&zWy z)wG+{HHG%loIe^a#VxCBVq??`3Ul>)6&n)i7F7BxZdt#U_-B*pNBMM^m+uQ|ePo#M z&%*6o@3{kvuR1UJ&EWdLy-`hPmbPOU2OFo|BD-k`*#|;j>{z(pe1pGPZ^3S_6n9 ze{BDj(y;00#(OgB4}NuWaJ&&K$~;+X&GKJ!1fCyUe!uVVg#X-54$WJ2jt90V$hc1S z~|}}!oF6kuiX)luwo*UFyn9k&+KZ9S=Sk~|I}!Ga1D9o znOku_Q!1kK=Gu>{3umxQ6-$*0pULv!@XTv>I+j>i38jCVU-gesp{@0iu8VWgJTH-x zO&4SypR2ODx~cW@y|pQx)6PupRNs6lblQ~%*NuWN=+7uJ?KjRmbK|jMN?^nN#)H>p z2=BY}>!HkjAE}q0J*L_9uX?DFV^XZsBh%YxQ7}(i;^Nb`{7YeWj z3(Byb6WUkCpKjRXQ7-Ply7>RRt)cTIdVW1__PF$gIbTb1nvY_~-H^(e>#kM?zDT-L z)jz*sdDLA6u@3+Joic~E2~N{tnQ&C;Z-n&$18Xt4eO^C&?hF54xTCnt$>rkS%F>Si zQyyNac4a z_yoVt)`JgNe|WoB30>I`>|y09G29RO+ClfE)+Xq*_&B#$7Ex|soi-O zeup`3+pjpmq-C@0?*nrfcCb4-?P@ya!YP<$CwAffT9MQpmre=$_^(mmXM8^4+}TE* znaVZ|M-&59pKY*A{g`7kVP=+>X`oflm$K4J%~2OJ&g_YiaTHK zOf}x87A2U|_-4lfW9@B!M2w3r?VK0s^~F*(aNY9vYn%IM-aJ_fUCqN`{n=M10JhxcPT&>qQUFU(dHJ;$6#wY5nj0 z-{nqmI{s<$>?_OS6)z+@%ljX4pBcJ}b#nV7uBBfk-Iu(G)LwRQwfK`_uWULjCU!4IDthkcZ?i*^;`<_Z^J$2N=TG2l zm8hE7DzH`h1U%FqWFS8 z*myTDvMW+Aah=ismQCG^A@9W2h9a*CIho8%X*Xkzoy$3xa$9KAnl0XXA9RgH`J?|x zr+B2w`5#u#E#B0kc9@C#!ak18Hl@vLn)b<6-Qxb(|8e`7Gu!VQS+Bjc`TXSP;@6Hz zhquh-`K{5r*zK4@-D%#wMyoW7_xl%~Su+2p_%}=IhIonn{2Y(-&c)A9tk&M~{=BE~ z48|Mw_pG&dRS4c`XG_>A!@fD;)4vxt|1NRoSaG3DAWHdr!JVYsSL>~2NSSXr!JK<^ z_qB%LqRlVg_ZQqL{Qd0JI~%Lr`;J|)p7Eo2=UBhvWA*R4 z|64D^?bys?v@lGH_5G3k|9``jbRT8bT0tC+7o zS3bZl^ylmKBSpVnuYb$;P_iR+!FiL#GZmOu2dfk{~{33m}qxo%_ zuiKulZMPNpZu4R8sn;p(GlX2rB2Rc#C&~MJ1o_UswRawm`|GrN6$A6CH?3F2n#zxD zw(VE%eX{TlLwx4d?eq9-PF_BEoH^v-i>RH4ggHa9Vh=6&8Nr(z#Xjfb$98pzq$T;4 zx@r8bzI>}W&m0TApJ*Q?EU33 #%5L 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 + {% endblock %} + + +Links +----- + +- Website: https://palletsprojects.com/p/jinja/ +- Documentation: https://jinja.palletsprojects.com/ +- Releases: https://pypi.org/project/Jinja2/ +- Code: https://github.com/pallets/jinja +- Issue tracker: https://github.com/pallets/jinja/issues +- Test status: https://dev.azure.com/pallets/jinja/_build +- Official chat: https://discord.gg/t6rrQZH + + diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/RECORD b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/RECORD new file mode 100644 index 00000000..413fef4b --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/RECORD @@ -0,0 +1,61 @@ +Jinja2-2.11.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Jinja2-2.11.2.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +Jinja2-2.11.2.dist-info/METADATA,sha256=5ZHRZoIRAMHsJPnqhlJ622_dRPsYePYJ-9EH4-Ry7yI,3535 +Jinja2-2.11.2.dist-info/RECORD,, +Jinja2-2.11.2.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +Jinja2-2.11.2.dist-info/entry_points.txt,sha256=Qy_DkVo6Xj_zzOtmErrATe8lHZhOqdjpt3e4JJAGyi8,61 +Jinja2-2.11.2.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +jinja2/__init__.py,sha256=0QCM_jKKDM10yzSdHRVV4mQbCbDqf0GN0GirAqibn9Y,1549 +jinja2/__pycache__/__init__.cpython-38.pyc,, +jinja2/__pycache__/_compat.cpython-38.pyc,, +jinja2/__pycache__/_identifier.cpython-38.pyc,, +jinja2/__pycache__/asyncfilters.cpython-38.pyc,, +jinja2/__pycache__/asyncsupport.cpython-38.pyc,, +jinja2/__pycache__/bccache.cpython-38.pyc,, +jinja2/__pycache__/compiler.cpython-38.pyc,, +jinja2/__pycache__/constants.cpython-38.pyc,, +jinja2/__pycache__/debug.cpython-38.pyc,, +jinja2/__pycache__/defaults.cpython-38.pyc,, +jinja2/__pycache__/environment.cpython-38.pyc,, +jinja2/__pycache__/exceptions.cpython-38.pyc,, +jinja2/__pycache__/ext.cpython-38.pyc,, +jinja2/__pycache__/filters.cpython-38.pyc,, +jinja2/__pycache__/idtracking.cpython-38.pyc,, +jinja2/__pycache__/lexer.cpython-38.pyc,, +jinja2/__pycache__/loaders.cpython-38.pyc,, +jinja2/__pycache__/meta.cpython-38.pyc,, +jinja2/__pycache__/nativetypes.cpython-38.pyc,, +jinja2/__pycache__/nodes.cpython-38.pyc,, +jinja2/__pycache__/optimizer.cpython-38.pyc,, +jinja2/__pycache__/parser.cpython-38.pyc,, +jinja2/__pycache__/runtime.cpython-38.pyc,, +jinja2/__pycache__/sandbox.cpython-38.pyc,, +jinja2/__pycache__/tests.cpython-38.pyc,, +jinja2/__pycache__/utils.cpython-38.pyc,, +jinja2/__pycache__/visitor.cpython-38.pyc,, +jinja2/_compat.py,sha256=B6Se8HjnXVpzz9-vfHejn-DV2NjaVK-Iewupc5kKlu8,3191 +jinja2/_identifier.py,sha256=EdgGJKi7O1yvr4yFlvqPNEqV6M1qHyQr8Gt8GmVTKVM,1775 +jinja2/asyncfilters.py,sha256=XJtYXTxFvcJ5xwk6SaDL4S0oNnT0wPYvXBCSzc482fI,4250 +jinja2/asyncsupport.py,sha256=ZBFsDLuq3Gtji3Ia87lcyuDbqaHZJRdtShZcqwpFnSQ,7209 +jinja2/bccache.py,sha256=3Pmp4jo65M9FQuIxdxoDBbEDFwe4acDMQf77nEJfrHA,12139 +jinja2/compiler.py,sha256=Ta9W1Lit542wItAHXlDcg0sEOsFDMirCdlFPHAurg4o,66284 +jinja2/constants.py,sha256=RR1sTzNzUmKco6aZicw4JpQpJGCuPuqm1h1YmCNUEFY,1458 +jinja2/debug.py,sha256=neR7GIGGjZH3_ILJGVUYy3eLQCCaWJMXOb7o0kGInWc,8529 +jinja2/defaults.py,sha256=85B6YUUCyWPSdrSeVhcqFVuu_bHUAQXeey--FIwSeVQ,1126 +jinja2/environment.py,sha256=XDSLKc4SqNLMOwTSq3TbWEyA5WyXfuLuVD0wAVjEFwM,50629 +jinja2/exceptions.py,sha256=VjNLawcmf2ODffqVMCQK1cRmvFaUfQWF4u8ouP3QPcE,5425 +jinja2/ext.py,sha256=AtwL5O5enT_L3HR9-oBvhGyUTdGoyaqG_ICtnR_EVd4,26441 +jinja2/filters.py,sha256=_RpPgAlgIj7ExvyDzcHAC3B36cocfWK-1TEketbNeM0,41415 +jinja2/idtracking.py,sha256=J3O4VHsrbf3wzwiBc7Cro26kHb6_5kbULeIOzocchIU,9211 +jinja2/lexer.py,sha256=nUFLRKhhKmmEWkLI65nQePgcQs7qsRdjVYZETMt_v0g,30331 +jinja2/loaders.py,sha256=C-fST_dmFjgWkp0ZuCkrgICAoOsoSIF28wfAFink0oU,17666 +jinja2/meta.py,sha256=QjyYhfNRD3QCXjBJpiPl9KgkEkGXJbAkCUq4-Ur10EQ,4131 +jinja2/nativetypes.py,sha256=Ul__gtVw4xH-0qvUvnCNHedQeNDwmEuyLJztzzSPeRg,2753 +jinja2/nodes.py,sha256=Mk1oJPVgIjnQw9WOqILvcu3rLepcFZ0ahxQm2mbwDwc,31095 +jinja2/optimizer.py,sha256=gQLlMYzvQhluhzmAIFA1tXS0cwgWYOjprN-gTRcHVsc,1457 +jinja2/parser.py,sha256=fcfdqePNTNyvosIvczbytVA332qpsURvYnCGcjDHSkA,35660 +jinja2/runtime.py,sha256=0y-BRyIEZ9ltByL2Id6GpHe1oDRQAwNeQvI0SKobNMw,30618 +jinja2/sandbox.py,sha256=knayyUvXsZ-F0mk15mO2-ehK9gsw04UhB8td-iUOtLc,17127 +jinja2/tests.py,sha256=iO_Y-9Vo60zrVe1lMpSl5sKHqAxe2leZHC08OoZ8K24,4799 +jinja2/utils.py,sha256=OoVMlQe9S2-lWT6jJbTu9tDuDvGNyWUhHDcE51i5_Do,22522 +jinja2/visitor.py,sha256=DUHupl0a4PGp7nxRtZFttUzAi1ccxzqc2hzetPYUz8U,3240 diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/WHEEL b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt new file mode 100644 index 00000000..3619483f --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[babel.extractors] +jinja2 = jinja2.ext:babel_extract [i18n] + diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt new file mode 100644 index 00000000..7f7afbf3 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA new file mode 100644 index 00000000..c50370d6 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA @@ -0,0 +1,105 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 1.1.1 +Summary: Safely add untrusted strings to HTML/XML markup. +Home-page: https://palletsprojects.com/p/markupsafe/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: The Pallets Team +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ +Project-URL: Code, https://github.com/pallets/markupsafe +Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* +Description-Content-Type: text/x-rst + +MarkupSafe +========== + +MarkupSafe implements a text object that escapes characters so it is +safe to use in HTML and XML. Characters that have special meanings are +replaced so that they display as the actual characters. This mitigates +injection attacks, meaning untrusted user input can safely be displayed +on a page. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U MarkupSafe + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +Examples +-------- + +.. code-block:: pycon + + >>> from markupsafe import Markup, escape + >>> # escape replaces special characters and wraps in Markup + >>> escape('') + Markup(u'<script>alert(document.cookie);</script>') + >>> # wrap in Markup to mark text "safe" and prevent escaping + >>> Markup('Hello') + Markup('hello') + >>> escape(Markup('Hello')) + Markup('hello') + >>> # Markup is a text subclass (str on Python 3, unicode on Python 2) + >>> # methods and operators escape their arguments + >>> template = Markup("Hello %s") + >>> template % '"World"' + Markup('Hello "World"') + + +Donate +------ + +The Pallets organization develops and supports MarkupSafe and other +libraries that use it. In order to grow the community of contributors +and users, and allow the maintainers to devote more time to the +projects, `please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +* Website: https://palletsprojects.com/p/markupsafe/ +* Documentation: https://markupsafe.palletsprojects.com/ +* License: `BSD-3-Clause `_ +* Releases: https://pypi.org/project/MarkupSafe/ +* Code: https://github.com/pallets/markupsafe +* Issue tracker: https://github.com/pallets/markupsafe/issues +* Test status: + + * Linux, Mac: https://travis-ci.org/pallets/markupsafe + * Windows: https://ci.appveyor.com/project/pallets/markupsafe + +* Test coverage: https://codecov.io/gh/pallets/markupsafe +* Official chat: https://discord.gg/t6rrQZH + + diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/RECORD b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/RECORD new file mode 100644 index 00000000..95c33399 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/RECORD @@ -0,0 +1,16 @@ +MarkupSafe-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +MarkupSafe-1.1.1.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +MarkupSafe-1.1.1.dist-info/METADATA,sha256=IFCP4hCNGjXJgMoSvdjPiKDLAMUTTWoxKXQsQvmyMNU,3653 +MarkupSafe-1.1.1.dist-info/RECORD,, +MarkupSafe-1.1.1.dist-info/WHEEL,sha256=VEyGcIFAmk_1KbI6gaZGw_mMiT-pdGweASQLX-DzYaY,108 +MarkupSafe-1.1.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=oTblO5f9KFM-pvnq9bB0HgElnqkJyqHnFN1Nx2NIvnY,10126 +markupsafe/__pycache__/__init__.cpython-38.pyc,, +markupsafe/__pycache__/_compat.cpython-38.pyc,, +markupsafe/__pycache__/_constants.cpython-38.pyc,, +markupsafe/__pycache__/_native.cpython-38.pyc,, +markupsafe/_compat.py,sha256=uEW1ybxEjfxIiuTbRRaJpHsPFf4yQUMMKaPgYEC5XbU,558 +markupsafe/_constants.py,sha256=zo2ajfScG-l1Sb_52EP3MlDCqO7Y1BVHUXXKRsVDRNk,4690 +markupsafe/_native.py,sha256=d-8S_zzYt2y512xYcuSxq0NeG2DUUvG80wVdTn-4KI8,1873 +markupsafe/_speedups.c,sha256=k0fzEIK3CP6MmMqeY0ob43TP90mVN0DTyn7BAl3RqSg,9884 +markupsafe/_speedups.cpython-38-x86_64-linux-gnu.so,sha256=SbJwN321Xn7OPYGv5a6Ghzga75uT8RHQUGkoQUASF-o,48016 diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL new file mode 100644 index 00000000..ae40efdd --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.31.1) +Root-Is-Purelib: false +Tag: cp38-cp38-manylinux1_x86_64 + diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt new file mode 100644 index 00000000..75bf7292 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/LICENSE b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/LICENSE new file mode 100644 index 00000000..3d82c281 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2017-2020 Ingy döt Net +Copyright (c) 2006-2016 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/METADATA b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/METADATA new file mode 100644 index 00000000..a70dd202 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/METADATA @@ -0,0 +1,41 @@ +Metadata-Version: 2.1 +Name: PyYAML +Version: 5.3.1 +Summary: YAML parser and emitter for Python +Home-page: https://github.com/yaml/pyyaml +Author: Kirill Simonov +Author-email: xi@resolvent.net +License: MIT +Download-URL: https://pypi.org/project/PyYAML/ +Platform: Any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Cython +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* + +YAML is a data serialization format designed for human readability +and interaction with scripting languages. PyYAML is a YAML parser +and emitter for Python. + +PyYAML features a complete YAML 1.1 parser, Unicode support, pickle +support, capable extension API, and sensible error messages. PyYAML +supports standard YAML tags and provides Python-specific tags that +allow to represent an arbitrary Python object. + +PyYAML is applicable for a broad range of tasks from complex +configuration files to object serialization and persistence. + diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/RECORD b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/RECORD new file mode 100644 index 00000000..cae61d97 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/RECORD @@ -0,0 +1,40 @@ +PyYAML-5.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +PyYAML-5.3.1.dist-info/LICENSE,sha256=xAESRJ8lS5dTBFklJIMT6ScO-jbSJrItgtTMbEPFfyk,1101 +PyYAML-5.3.1.dist-info/METADATA,sha256=xTsZFjd8T4M-5rC2M3BHgx_KTTpEPy5vFDIXrbzRXPQ,1758 +PyYAML-5.3.1.dist-info/RECORD,, +PyYAML-5.3.1.dist-info/WHEEL,sha256=TpFVeXF_cAlV118WSIPWtjqW7nPvzoOw-49FmS3fDKQ,103 +PyYAML-5.3.1.dist-info/top_level.txt,sha256=rpj0IVMTisAjh_1vG3Ccf9v5jpCQwAz6cD1IVU5ZdhQ,11 +yaml/__init__.py,sha256=XFUNbKTg4afAd0BETjGQ1mKQ97_g5jbE1C0WoKc74dc,13170 +yaml/__pycache__/__init__.cpython-38.pyc,, +yaml/__pycache__/composer.cpython-38.pyc,, +yaml/__pycache__/constructor.cpython-38.pyc,, +yaml/__pycache__/cyaml.cpython-38.pyc,, +yaml/__pycache__/dumper.cpython-38.pyc,, +yaml/__pycache__/emitter.cpython-38.pyc,, +yaml/__pycache__/error.cpython-38.pyc,, +yaml/__pycache__/events.cpython-38.pyc,, +yaml/__pycache__/loader.cpython-38.pyc,, +yaml/__pycache__/nodes.cpython-38.pyc,, +yaml/__pycache__/parser.cpython-38.pyc,, +yaml/__pycache__/reader.cpython-38.pyc,, +yaml/__pycache__/representer.cpython-38.pyc,, +yaml/__pycache__/resolver.cpython-38.pyc,, +yaml/__pycache__/scanner.cpython-38.pyc,, +yaml/__pycache__/serializer.cpython-38.pyc,, +yaml/__pycache__/tokens.cpython-38.pyc,, +yaml/composer.py,sha256=_Ko30Wr6eDWUeUpauUGT3Lcg9QPBnOPVlTnIMRGJ9FM,4883 +yaml/constructor.py,sha256=O3Uaf0_J_5GQBoeI9ZNhpJAhtdagr_X2HzDgGbZOMnw,28627 +yaml/cyaml.py,sha256=LiMkvchNonfoy1F6ec9L2BiUz3r0bwF4hympASJX1Ic,3846 +yaml/dumper.py,sha256=PLctZlYwZLp7XmeUdwRuv4nYOZ2UBnDIUy8-lKfLF-o,2837 +yaml/emitter.py,sha256=jghtaU7eFwg31bG0B7RZea_29Adi9CKmXq_QjgQpCkQ,43006 +yaml/error.py,sha256=Ah9z-toHJUbE9j-M8YpxgSRM5CgLCcwVzJgLLRF2Fxo,2533 +yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445 +yaml/loader.py,sha256=UVa-zIqmkFSCIYq_PgSGm4NSJttHY2Rf_zQ4_b1fHN0,2061 +yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440 +yaml/parser.py,sha256=ilWp5vvgoHFGzvOZDItFoGjD6D42nhlZrZyjAwa0oJo,25495 +yaml/reader.py,sha256=0dmzirOiDG4Xo41RnuQS7K9rkY3xjHiVasfDMNTqCNw,6794 +yaml/representer.py,sha256=82UM3ZxUQKqsKAF4ltWOxCS6jGPIFtXpGs7mvqyv4Xs,14184 +yaml/resolver.py,sha256=DJCjpQr8YQCEYYjKEYqTl0GrsZil2H4aFOI9b0Oe-U4,8970 +yaml/scanner.py,sha256=KeQIKGNlSyPE8QDwionHxy9CgbqE5teJEz05FR9-nAg,51277 +yaml/serializer.py,sha256=ChuFgmhU01hj4xgI8GaKv6vfM2Bujwa9i7d2FAHj7cA,4165 +yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573 diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/WHEEL b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/WHEEL new file mode 100644 index 00000000..d193dea9 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: false +Tag: cp38-cp38-linux_x86_64 + diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt new file mode 100644 index 00000000..e6475e91 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_yaml +yaml diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/__init__.py b/magma/squid_cnf/charms/squid/venv/jinja2/__init__.py new file mode 100644 index 00000000..1229ba42 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/__init__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +"""Jinja is a template engine written in pure Python. It provides a +non-XML syntax that supports inline expressions and an optional +sandboxed environment. +""" +from markupsafe import escape +from markupsafe import Markup + +from .bccache import BytecodeCache +from .bccache import FileSystemBytecodeCache +from .bccache import MemcachedBytecodeCache +from .environment import Environment +from .environment import Template +from .exceptions import TemplateAssertionError +from .exceptions import TemplateError +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .filters import contextfilter +from .filters import environmentfilter +from .filters import evalcontextfilter +from .loaders import BaseLoader +from .loaders import ChoiceLoader +from .loaders import DictLoader +from .loaders import FileSystemLoader +from .loaders import FunctionLoader +from .loaders import ModuleLoader +from .loaders import PackageLoader +from .loaders import PrefixLoader +from .runtime import ChainableUndefined +from .runtime import DebugUndefined +from .runtime import make_logging_undefined +from .runtime import StrictUndefined +from .runtime import Undefined +from .utils import clear_caches +from .utils import contextfunction +from .utils import environmentfunction +from .utils import evalcontextfunction +from .utils import is_undefined +from .utils import select_autoescape + +__version__ = "2.11.2" diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/_compat.py b/magma/squid_cnf/charms/squid/venv/jinja2/_compat.py new file mode 100644 index 00000000..1f044954 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/_compat.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# flake8: noqa +import marshal +import sys + +PY2 = sys.version_info[0] == 2 +PYPY = hasattr(sys, "pypy_translation_info") +_identity = lambda x: x + +if not PY2: + unichr = chr + range_type = range + text_type = str + string_types = (str,) + integer_types = (int,) + + iterkeys = lambda d: iter(d.keys()) + itervalues = lambda d: iter(d.values()) + iteritems = lambda d: iter(d.items()) + + import pickle + from io import BytesIO, StringIO + + NativeStringIO = StringIO + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + + ifilter = filter + imap = map + izip = zip + intern = sys.intern + + implements_iterator = _identity + implements_to_string = _identity + encode_filename = _identity + + marshal_dump = marshal.dump + marshal_load = marshal.load + +else: + unichr = unichr + text_type = unicode + range_type = xrange + string_types = (str, unicode) + integer_types = (int, long) + + iterkeys = lambda d: d.iterkeys() + itervalues = lambda d: d.itervalues() + iteritems = lambda d: d.iteritems() + + import cPickle as pickle + from cStringIO import StringIO as BytesIO, StringIO + + NativeStringIO = BytesIO + + exec("def reraise(tp, value, tb=None):\n raise tp, value, tb") + + from itertools import imap, izip, ifilter + + intern = intern + + def implements_iterator(cls): + cls.next = cls.__next__ + del cls.__next__ + return cls + + def implements_to_string(cls): + cls.__unicode__ = cls.__str__ + cls.__str__ = lambda x: x.__unicode__().encode("utf-8") + return cls + + def encode_filename(filename): + if isinstance(filename, unicode): + return filename.encode("utf-8") + return filename + + def marshal_dump(code, f): + if isinstance(f, file): + marshal.dump(code, f) + else: + f.write(marshal.dumps(code)) + + def marshal_load(f): + if isinstance(f, file): + return marshal.load(f) + return marshal.loads(f.read()) + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a + # dummy metaclass for one level of class instantiation that replaces + # itself with the actual metaclass. + class metaclass(type): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + return type.__new__(metaclass, "temporary_class", (), {}) + + +try: + from urllib.parse import quote_from_bytes as url_quote +except ImportError: + from urllib import quote as url_quote + + +try: + from collections import abc +except ImportError: + import collections as abc + + +try: + from os import fspath +except ImportError: + try: + from pathlib import PurePath + except ImportError: + PurePath = None + + def fspath(path): + if hasattr(path, "__fspath__"): + return path.__fspath__() + + # Python 3.5 doesn't have __fspath__ yet, use str. + if PurePath is not None and isinstance(path, PurePath): + return str(path) + + return path diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py b/magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py new file mode 100644 index 00000000..224d5449 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py @@ -0,0 +1,6 @@ +import re + +# generated by scripts/generate_identifier_pattern.py +pattern = re.compile( + r"[\w·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఃా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑅳𑄴𑆀-𑆂𑆳-𑇊𑇀-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯]+" # noqa: B950 +) diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py b/magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py new file mode 100644 index 00000000..3d98dbcc --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py @@ -0,0 +1,158 @@ +from functools import wraps + +from . import filters +from .asyncsupport import auto_aiter +from .asyncsupport import auto_await + + +async def auto_to_seq(value): + seq = [] + if hasattr(value, "__aiter__"): + async for item in value: + seq.append(item) + else: + for item in value: + seq.append(item) + return seq + + +async def async_select_or_reject(args, kwargs, modfunc, lookup_attr): + seq, func = filters.prepare_select_or_reject(args, kwargs, modfunc, lookup_attr) + if seq: + async for item in auto_aiter(seq): + if func(item): + yield item + + +def dualfilter(normal_filter, async_filter): + wrap_evalctx = False + if getattr(normal_filter, "environmentfilter", False) is True: + + def is_async(args): + return args[0].is_async + + wrap_evalctx = False + else: + has_evalctxfilter = getattr(normal_filter, "evalcontextfilter", False) is True + has_ctxfilter = getattr(normal_filter, "contextfilter", False) is True + wrap_evalctx = not has_evalctxfilter and not has_ctxfilter + + def is_async(args): + return args[0].environment.is_async + + @wraps(normal_filter) + def wrapper(*args, **kwargs): + b = is_async(args) + if wrap_evalctx: + args = args[1:] + if b: + return async_filter(*args, **kwargs) + return normal_filter(*args, **kwargs) + + if wrap_evalctx: + wrapper.evalcontextfilter = True + + wrapper.asyncfiltervariant = True + + return wrapper + + +def asyncfiltervariant(original): + def decorator(f): + return dualfilter(original, f) + + return decorator + + +@asyncfiltervariant(filters.do_first) +async def do_first(environment, seq): + try: + return await auto_aiter(seq).__anext__() + except StopAsyncIteration: + return environment.undefined("No first item, sequence was empty.") + + +@asyncfiltervariant(filters.do_groupby) +async def do_groupby(environment, value, attribute): + expr = filters.make_attrgetter(environment, attribute) + return [ + filters._GroupTuple(key, await auto_to_seq(values)) + for key, values in filters.groupby( + sorted(await auto_to_seq(value), key=expr), expr + ) + ] + + +@asyncfiltervariant(filters.do_join) +async def do_join(eval_ctx, value, d=u"", attribute=None): + return filters.do_join(eval_ctx, await auto_to_seq(value), d, attribute) + + +@asyncfiltervariant(filters.do_list) +async def do_list(value): + return await auto_to_seq(value) + + +@asyncfiltervariant(filters.do_reject) +async def do_reject(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: not x, False) + + +@asyncfiltervariant(filters.do_rejectattr) +async def do_rejectattr(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: not x, True) + + +@asyncfiltervariant(filters.do_select) +async def do_select(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: x, False) + + +@asyncfiltervariant(filters.do_selectattr) +async def do_selectattr(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: x, True) + + +@asyncfiltervariant(filters.do_map) +async def do_map(*args, **kwargs): + seq, func = filters.prepare_map(args, kwargs) + if seq: + async for item in auto_aiter(seq): + yield await auto_await(func(item)) + + +@asyncfiltervariant(filters.do_sum) +async def do_sum(environment, iterable, attribute=None, start=0): + rv = start + if attribute is not None: + func = filters.make_attrgetter(environment, attribute) + else: + + def func(x): + return x + + async for item in auto_aiter(iterable): + rv += func(item) + return rv + + +@asyncfiltervariant(filters.do_slice) +async def do_slice(value, slices, fill_with=None): + return filters.do_slice(await auto_to_seq(value), slices, fill_with) + + +ASYNC_FILTERS = { + "first": do_first, + "groupby": do_groupby, + "join": do_join, + "list": do_list, + # we intentionally do not support do_last because that would be + # ridiculous + "reject": do_reject, + "rejectattr": do_rejectattr, + "map": do_map, + "select": do_select, + "selectattr": do_selectattr, + "sum": do_sum, + "slice": do_slice, +} diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py b/magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py new file mode 100644 index 00000000..78ba3739 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py @@ -0,0 +1,264 @@ +# -*- coding: utf-8 -*- +"""The code for async support. Importing this patches Jinja on supported +Python versions. +""" +import asyncio +import inspect +from functools import update_wrapper + +from markupsafe import Markup + +from .environment import TemplateModule +from .runtime import LoopContext +from .utils import concat +from .utils import internalcode +from .utils import missing + + +async def concat_async(async_gen): + rv = [] + + async def collect(): + async for event in async_gen: + rv.append(event) + + await collect() + return concat(rv) + + +async def generate_async(self, *args, **kwargs): + vars = dict(*args, **kwargs) + try: + async for event in self.root_render_func(self.new_context(vars)): + yield event + except Exception: + yield self.environment.handle_exception() + + +def wrap_generate_func(original_generate): + def _convert_generator(self, loop, args, kwargs): + async_gen = self.generate_async(*args, **kwargs) + try: + while 1: + yield loop.run_until_complete(async_gen.__anext__()) + except StopAsyncIteration: + pass + + def generate(self, *args, **kwargs): + if not self.environment.is_async: + return original_generate(self, *args, **kwargs) + return _convert_generator(self, asyncio.get_event_loop(), args, kwargs) + + return update_wrapper(generate, original_generate) + + +async def render_async(self, *args, **kwargs): + if not self.environment.is_async: + raise RuntimeError("The environment was not created with async mode enabled.") + + vars = dict(*args, **kwargs) + ctx = self.new_context(vars) + + try: + return await concat_async(self.root_render_func(ctx)) + except Exception: + return self.environment.handle_exception() + + +def wrap_render_func(original_render): + def render(self, *args, **kwargs): + if not self.environment.is_async: + return original_render(self, *args, **kwargs) + loop = asyncio.get_event_loop() + return loop.run_until_complete(self.render_async(*args, **kwargs)) + + return update_wrapper(render, original_render) + + +def wrap_block_reference_call(original_call): + @internalcode + async def async_call(self): + rv = await concat_async(self._stack[self._depth](self._context)) + if self._context.eval_ctx.autoescape: + rv = Markup(rv) + return rv + + @internalcode + def __call__(self): + if not self._context.environment.is_async: + return original_call(self) + return async_call(self) + + return update_wrapper(__call__, original_call) + + +def wrap_macro_invoke(original_invoke): + @internalcode + async def async_invoke(self, arguments, autoescape): + rv = await self._func(*arguments) + if autoescape: + rv = Markup(rv) + return rv + + @internalcode + def _invoke(self, arguments, autoescape): + if not self._environment.is_async: + return original_invoke(self, arguments, autoescape) + return async_invoke(self, arguments, autoescape) + + return update_wrapper(_invoke, original_invoke) + + +@internalcode +async def get_default_module_async(self): + if self._module is not None: + return self._module + self._module = rv = await self.make_module_async() + return rv + + +def wrap_default_module(original_default_module): + @internalcode + def _get_default_module(self): + if self.environment.is_async: + raise RuntimeError("Template module attribute is unavailable in async mode") + return original_default_module(self) + + return _get_default_module + + +async def make_module_async(self, vars=None, shared=False, locals=None): + context = self.new_context(vars, shared, locals) + body_stream = [] + async for item in self.root_render_func(context): + body_stream.append(item) + return TemplateModule(self, context, body_stream) + + +def patch_template(): + from . import Template + + Template.generate = wrap_generate_func(Template.generate) + Template.generate_async = update_wrapper(generate_async, Template.generate_async) + Template.render_async = update_wrapper(render_async, Template.render_async) + Template.render = wrap_render_func(Template.render) + Template._get_default_module = wrap_default_module(Template._get_default_module) + Template._get_default_module_async = get_default_module_async + Template.make_module_async = update_wrapper( + make_module_async, Template.make_module_async + ) + + +def patch_runtime(): + from .runtime import BlockReference, Macro + + BlockReference.__call__ = wrap_block_reference_call(BlockReference.__call__) + Macro._invoke = wrap_macro_invoke(Macro._invoke) + + +def patch_filters(): + from .filters import FILTERS + from .asyncfilters import ASYNC_FILTERS + + FILTERS.update(ASYNC_FILTERS) + + +def patch_all(): + patch_template() + patch_runtime() + patch_filters() + + +async def auto_await(value): + if inspect.isawaitable(value): + return await value + return value + + +async def auto_aiter(iterable): + if hasattr(iterable, "__aiter__"): + async for item in iterable: + yield item + return + for item in iterable: + yield item + + +class AsyncLoopContext(LoopContext): + _to_iterator = staticmethod(auto_aiter) + + @property + async def length(self): + if self._length is not None: + return self._length + + try: + self._length = len(self._iterable) + except TypeError: + iterable = [x async for x in self._iterator] + self._iterator = self._to_iterator(iterable) + self._length = len(iterable) + self.index + (self._after is not missing) + + return self._length + + @property + async def revindex0(self): + return await self.length - self.index + + @property + async def revindex(self): + return await self.length - self.index0 + + async def _peek_next(self): + if self._after is not missing: + return self._after + + try: + self._after = await self._iterator.__anext__() + except StopAsyncIteration: + self._after = missing + + return self._after + + @property + async def last(self): + return await self._peek_next() is missing + + @property + async def nextitem(self): + rv = await self._peek_next() + + if rv is missing: + return self._undefined("there is no next item") + + return rv + + def __aiter__(self): + return self + + async def __anext__(self): + if self._after is not missing: + rv = self._after + self._after = missing + else: + rv = await self._iterator.__anext__() + + self.index0 += 1 + self._before = self._current + self._current = rv + return rv, self + + +async def make_async_loop_context(iterable, undefined, recurse=None, depth0=0): + import warnings + + warnings.warn( + "This template must be recompiled with at least Jinja 2.11, or" + " it will fail in 3.0.", + DeprecationWarning, + stacklevel=2, + ) + return AsyncLoopContext(iterable, undefined, recurse, depth0) + + +patch_all() diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/bccache.py b/magma/squid_cnf/charms/squid/venv/jinja2/bccache.py new file mode 100644 index 00000000..9c066103 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/bccache.py @@ -0,0 +1,350 @@ +# -*- coding: utf-8 -*- +"""The optional bytecode cache system. This is useful if you have very +complex template situations and the compilation of all those templates +slows down your application too much. + +Situations where this is useful are often forking web applications that +are initialized on the first request. +""" +import errno +import fnmatch +import os +import stat +import sys +import tempfile +from hashlib import sha1 +from os import listdir +from os import path + +from ._compat import BytesIO +from ._compat import marshal_dump +from ._compat import marshal_load +from ._compat import pickle +from ._compat import text_type +from .utils import open_if_exists + +bc_version = 4 +# Magic bytes to identify Jinja bytecode cache files. Contains the +# Python major and minor version to avoid loading incompatible bytecode +# if a project upgrades its Python version. +bc_magic = ( + b"j2" + + pickle.dumps(bc_version, 2) + + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2) +) + + +class Bucket(object): + """Buckets are used to store the bytecode for one template. It's created + and initialized by the bytecode cache and passed to the loading functions. + + The buckets get an internal checksum from the cache assigned and use this + to automatically reject outdated cache material. Individual bytecode + cache subclasses don't have to care about cache invalidation. + """ + + def __init__(self, environment, key, checksum): + self.environment = environment + self.key = key + self.checksum = checksum + self.reset() + + def reset(self): + """Resets the bucket (unloads the bytecode).""" + self.code = None + + def load_bytecode(self, f): + """Loads bytecode from a file or file like object.""" + # make sure the magic header is correct + magic = f.read(len(bc_magic)) + if magic != bc_magic: + self.reset() + return + # the source code of the file changed, we need to reload + checksum = pickle.load(f) + if self.checksum != checksum: + self.reset() + return + # if marshal_load fails then we need to reload + try: + self.code = marshal_load(f) + except (EOFError, ValueError, TypeError): + self.reset() + return + + def write_bytecode(self, f): + """Dump the bytecode into the file or file like object passed.""" + if self.code is None: + raise TypeError("can't write empty bucket") + f.write(bc_magic) + pickle.dump(self.checksum, f, 2) + marshal_dump(self.code, f) + + def bytecode_from_string(self, string): + """Load bytecode from a string.""" + self.load_bytecode(BytesIO(string)) + + def bytecode_to_string(self): + """Return the bytecode as string.""" + out = BytesIO() + self.write_bytecode(out) + return out.getvalue() + + +class BytecodeCache(object): + """To implement your own bytecode cache you have to subclass this class + and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of + these methods are passed a :class:`~jinja2.bccache.Bucket`. + + A very basic bytecode cache that saves the bytecode on the file system:: + + from os import path + + class MyCache(BytecodeCache): + + def __init__(self, directory): + self.directory = directory + + def load_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + if path.exists(filename): + with open(filename, 'rb') as f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + with open(filename, 'wb') as f: + bucket.write_bytecode(f) + + A more advanced version of a filesystem based bytecode cache is part of + Jinja. + """ + + def load_bytecode(self, bucket): + """Subclasses have to override this method to load bytecode into a + bucket. If they are not able to find code in the cache for the + bucket, it must not do anything. + """ + raise NotImplementedError() + + def dump_bytecode(self, bucket): + """Subclasses have to override this method to write the bytecode + from a bucket back to the cache. If it unable to do so it must not + fail silently but raise an exception. + """ + raise NotImplementedError() + + def clear(self): + """Clears the cache. This method is not used by Jinja but should be + implemented to allow applications to clear the bytecode cache used + by a particular environment. + """ + + def get_cache_key(self, name, filename=None): + """Returns the unique hash key for this template name.""" + hash = sha1(name.encode("utf-8")) + if filename is not None: + filename = "|" + filename + if isinstance(filename, text_type): + filename = filename.encode("utf-8") + hash.update(filename) + return hash.hexdigest() + + def get_source_checksum(self, source): + """Returns a checksum for the source.""" + return sha1(source.encode("utf-8")).hexdigest() + + def get_bucket(self, environment, name, filename, source): + """Return a cache bucket for the given template. All arguments are + mandatory but filename may be `None`. + """ + key = self.get_cache_key(name, filename) + checksum = self.get_source_checksum(source) + bucket = Bucket(environment, key, checksum) + self.load_bytecode(bucket) + return bucket + + def set_bucket(self, bucket): + """Put the bucket into the cache.""" + self.dump_bytecode(bucket) + + +class FileSystemBytecodeCache(BytecodeCache): + """A bytecode cache that stores bytecode on the filesystem. It accepts + two arguments: The directory where the cache items are stored and a + pattern string that is used to build the filename. + + If no directory is specified a default cache directory is selected. On + Windows the user's temp directory is used, on UNIX systems a directory + is created for the user in the system temp directory. + + The pattern can be used to have multiple separate caches operate on the + same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` + is replaced with the cache key. + + >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') + + This bytecode cache supports clearing of the cache using the clear method. + """ + + def __init__(self, directory=None, pattern="__jinja2_%s.cache"): + if directory is None: + directory = self._get_default_cache_dir() + self.directory = directory + self.pattern = pattern + + def _get_default_cache_dir(self): + def _unsafe_dir(): + raise RuntimeError( + "Cannot determine safe temp directory. You " + "need to explicitly provide one." + ) + + tmpdir = tempfile.gettempdir() + + # On windows the temporary directory is used specific unless + # explicitly forced otherwise. We can just use that. + if os.name == "nt": + return tmpdir + if not hasattr(os, "getuid"): + _unsafe_dir() + + dirname = "_jinja2-cache-%d" % os.getuid() + actual_dir = os.path.join(tmpdir, dirname) + + try: + os.mkdir(actual_dir, stat.S_IRWXU) + except OSError as e: + if e.errno != errno.EEXIST: + raise + try: + os.chmod(actual_dir, stat.S_IRWXU) + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + except OSError as e: + if e.errno != errno.EEXIST: + raise + + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + + return actual_dir + + def _get_cache_filename(self, bucket): + return path.join(self.directory, self.pattern % bucket.key) + + def load_bytecode(self, bucket): + f = open_if_exists(self._get_cache_filename(bucket), "rb") + if f is not None: + try: + bucket.load_bytecode(f) + finally: + f.close() + + def dump_bytecode(self, bucket): + f = open(self._get_cache_filename(bucket), "wb") + try: + bucket.write_bytecode(f) + finally: + f.close() + + def clear(self): + # imported lazily here because google app-engine doesn't support + # write access on the file system and the function does not exist + # normally. + from os import remove + + files = fnmatch.filter(listdir(self.directory), self.pattern % "*") + for filename in files: + try: + remove(path.join(self.directory, filename)) + except OSError: + pass + + +class MemcachedBytecodeCache(BytecodeCache): + """This class implements a bytecode cache that uses a memcache cache for + storing the information. It does not enforce a specific memcache library + (tummy's memcache or cmemcache) but will accept any class that provides + the minimal interface required. + + Libraries compatible with this class: + + - `cachelib `_ + - `python-memcached `_ + + (Unfortunately the django cache interface is not compatible because it + does not support storing binary data, only unicode. You can however pass + the underlying cache client to the bytecode cache which is available + as `django.core.cache.cache._client`.) + + The minimal interface for the client passed to the constructor is this: + + .. class:: MinimalClientInterface + + .. method:: set(key, value[, timeout]) + + Stores the bytecode in the cache. `value` is a string and + `timeout` the timeout of the key. If timeout is not provided + a default timeout or no timeout should be assumed, if it's + provided it's an integer with the number of seconds the cache + item should exist. + + .. method:: get(key) + + Returns the value for the cache key. If the item does not + exist in the cache the return value must be `None`. + + The other arguments to the constructor are the prefix for all keys that + is added before the actual cache key and the timeout for the bytecode in + the cache system. We recommend a high (or no) timeout. + + This bytecode cache does not support clearing of used items in the cache. + The clear method is a no-operation function. + + .. versionadded:: 2.7 + Added support for ignoring memcache errors through the + `ignore_memcache_errors` parameter. + """ + + def __init__( + self, + client, + prefix="jinja2/bytecode/", + timeout=None, + ignore_memcache_errors=True, + ): + self.client = client + self.prefix = prefix + self.timeout = timeout + self.ignore_memcache_errors = ignore_memcache_errors + + def load_bytecode(self, bucket): + try: + code = self.client.get(self.prefix + bucket.key) + except Exception: + if not self.ignore_memcache_errors: + raise + code = None + if code is not None: + bucket.bytecode_from_string(code) + + def dump_bytecode(self, bucket): + args = (self.prefix + bucket.key, bucket.bytecode_to_string()) + if self.timeout is not None: + args += (self.timeout,) + try: + self.client.set(*args) + except Exception: + if not self.ignore_memcache_errors: + raise diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/compiler.py b/magma/squid_cnf/charms/squid/venv/jinja2/compiler.py new file mode 100644 index 00000000..63297b42 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/compiler.py @@ -0,0 +1,1843 @@ +# -*- coding: utf-8 -*- +"""Compiles nodes from the parser into Python code.""" +from collections import namedtuple +from functools import update_wrapper +from itertools import chain +from keyword import iskeyword as is_python_keyword + +from markupsafe import escape +from markupsafe import Markup + +from . import nodes +from ._compat import imap +from ._compat import iteritems +from ._compat import izip +from ._compat import NativeStringIO +from ._compat import range_type +from ._compat import string_types +from ._compat import text_type +from .exceptions import TemplateAssertionError +from .idtracking import Symbols +from .idtracking import VAR_LOAD_ALIAS +from .idtracking import VAR_LOAD_PARAMETER +from .idtracking import VAR_LOAD_RESOLVE +from .idtracking import VAR_LOAD_UNDEFINED +from .nodes import EvalContext +from .optimizer import Optimizer +from .utils import concat +from .visitor import NodeVisitor + +operators = { + "eq": "==", + "ne": "!=", + "gt": ">", + "gteq": ">=", + "lt": "<", + "lteq": "<=", + "in": "in", + "notin": "not in", +} + +# what method to iterate over items do we want to use for dict iteration +# in generated code? on 2.x let's go with iteritems, on 3.x with items +if hasattr(dict, "iteritems"): + dict_item_iter = "iteritems" +else: + dict_item_iter = "items" + +code_features = ["division"] + +# does this python version support generator stops? (PEP 0479) +try: + exec("from __future__ import generator_stop") + code_features.append("generator_stop") +except SyntaxError: + pass + +# does this python version support yield from? +try: + exec("def f(): yield from x()") +except SyntaxError: + supports_yield_from = False +else: + supports_yield_from = True + + +def optimizeconst(f): + def new_func(self, node, frame, **kwargs): + # Only optimize if the frame is not volatile + if self.optimized and not frame.eval_ctx.volatile: + new_node = self.optimizer.visit(node, frame.eval_ctx) + if new_node != node: + return self.visit(new_node, frame) + return f(self, node, frame, **kwargs) + + return update_wrapper(new_func, f) + + +def generate( + node, environment, name, filename, stream=None, defer_init=False, optimized=True +): + """Generate the python source for a node tree.""" + if not isinstance(node, nodes.Template): + raise TypeError("Can't compile non template nodes") + generator = environment.code_generator_class( + environment, name, filename, stream, defer_init, optimized + ) + generator.visit(node) + if stream is None: + return generator.stream.getvalue() + + +def has_safe_repr(value): + """Does the node have a safe representation?""" + if value is None or value is NotImplemented or value is Ellipsis: + return True + if type(value) in (bool, int, float, complex, range_type, Markup) + string_types: + return True + if type(value) in (tuple, list, set, frozenset): + for item in value: + if not has_safe_repr(item): + return False + return True + elif type(value) is dict: + for key, value in iteritems(value): + if not has_safe_repr(key): + return False + if not has_safe_repr(value): + return False + return True + return False + + +def find_undeclared(nodes, names): + """Check if the names passed are accessed undeclared. The return value + is a set of all the undeclared names from the sequence of names found. + """ + visitor = UndeclaredNameVisitor(names) + try: + for node in nodes: + visitor.visit(node) + except VisitorExit: + pass + return visitor.undeclared + + +class MacroRef(object): + def __init__(self, node): + self.node = node + self.accesses_caller = False + self.accesses_kwargs = False + self.accesses_varargs = False + + +class Frame(object): + """Holds compile time information for us.""" + + def __init__(self, eval_ctx, parent=None, level=None): + self.eval_ctx = eval_ctx + self.symbols = Symbols(parent and parent.symbols or None, level=level) + + # a toplevel frame is the root + soft frames such as if conditions. + self.toplevel = False + + # the root frame is basically just the outermost frame, so no if + # conditions. This information is used to optimize inheritance + # situations. + self.rootlevel = False + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = parent and parent.require_output_check + + # inside some tags we are using a buffer rather than yield statements. + # this for example affects {% filter %} or {% macro %}. If a frame + # is buffered this variable points to the name of the list used as + # buffer. + self.buffer = None + + # the name of the block we're in, otherwise None. + self.block = parent and parent.block or None + + # the parent of this frame + self.parent = parent + + if parent is not None: + self.buffer = parent.buffer + + def copy(self): + """Create a copy of the current one.""" + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.symbols = self.symbols.copy() + return rv + + def inner(self, isolated=False): + """Return an inner frame.""" + if isolated: + return Frame(self.eval_ctx, level=self.symbols.level + 1) + return Frame(self.eval_ctx, self) + + def soft(self): + """Return a soft frame. A soft frame may not be modified as + standalone thing as it shares the resources with the frame it + was created of, but it's not a rootlevel frame any longer. + + This is only used to implement if-statements. + """ + rv = self.copy() + rv.rootlevel = False + return rv + + __copy__ = copy + + +class VisitorExit(RuntimeError): + """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" + + +class DependencyFinderVisitor(NodeVisitor): + """A visitor that collects filter and test calls.""" + + def __init__(self): + self.filters = set() + self.tests = set() + + def visit_Filter(self, node): + self.generic_visit(node) + self.filters.add(node.name) + + def visit_Test(self, node): + self.generic_visit(node) + self.tests.add(node.name) + + def visit_Block(self, node): + """Stop visiting at blocks.""" + + +class UndeclaredNameVisitor(NodeVisitor): + """A visitor that checks if a name is accessed without being + declared. This is different from the frame visitor as it will + not stop at closure frames. + """ + + def __init__(self, names): + self.names = set(names) + self.undeclared = set() + + def visit_Name(self, node): + if node.ctx == "load" and node.name in self.names: + self.undeclared.add(node.name) + if self.undeclared == self.names: + raise VisitorExit() + else: + self.names.discard(node.name) + + def visit_Block(self, node): + """Stop visiting a blocks.""" + + +class CompilerExit(Exception): + """Raised if the compiler encountered a situation where it just + doesn't make sense to further process the code. Any block that + raises such an exception is not further processed. + """ + + +class CodeGenerator(NodeVisitor): + def __init__( + self, environment, name, filename, stream=None, defer_init=False, optimized=True + ): + if stream is None: + stream = NativeStringIO() + self.environment = environment + self.name = name + self.filename = filename + self.stream = stream + self.created_block_context = False + self.defer_init = defer_init + self.optimized = optimized + if optimized: + self.optimizer = Optimizer(environment) + + # aliases for imports + self.import_aliases = {} + + # a registry for all blocks. Because blocks are moved out + # into the global python scope they are registered here + self.blocks = {} + + # the number of extends statements so far + self.extends_so_far = 0 + + # some templates have a rootlevel extends. In this case we + # can safely assume that we're a child template and do some + # more optimizations. + self.has_known_extends = False + + # the current line number + self.code_lineno = 1 + + # registry of all filters and tests (global, not block local) + self.tests = {} + self.filters = {} + + # the debug information + self.debug_info = [] + self._write_debug_info = None + + # the number of new lines before the next write() + self._new_lines = 0 + + # the line number of the last written statement + self._last_line = 0 + + # true if nothing was written so far. + self._first_write = True + + # used by the `temporary_identifier` method to get new + # unique, temporary identifier + self._last_identifier = 0 + + # the current indentation + self._indentation = 0 + + # Tracks toplevel assignments + self._assign_stack = [] + + # Tracks parameter definition blocks + self._param_def_block = [] + + # Tracks the current context. + self._context_reference_stack = ["context"] + + # -- Various compilation helpers + + def fail(self, msg, lineno): + """Fail with a :exc:`TemplateAssertionError`.""" + raise TemplateAssertionError(msg, lineno, self.name, self.filename) + + def temporary_identifier(self): + """Get a new unique identifier.""" + self._last_identifier += 1 + return "t_%d" % self._last_identifier + + def buffer(self, frame): + """Enable buffering for the frame from that point onwards.""" + frame.buffer = self.temporary_identifier() + self.writeline("%s = []" % frame.buffer) + + def return_buffer_contents(self, frame, force_unescaped=False): + """Return the buffer contents of the frame.""" + if not force_unescaped: + if frame.eval_ctx.volatile: + self.writeline("if context.eval_ctx.autoescape:") + self.indent() + self.writeline("return Markup(concat(%s))" % frame.buffer) + self.outdent() + self.writeline("else:") + self.indent() + self.writeline("return concat(%s)" % frame.buffer) + self.outdent() + return + elif frame.eval_ctx.autoescape: + self.writeline("return Markup(concat(%s))" % frame.buffer) + return + self.writeline("return concat(%s)" % frame.buffer) + + def indent(self): + """Indent by one.""" + self._indentation += 1 + + def outdent(self, step=1): + """Outdent by step.""" + self._indentation -= step + + def start_write(self, frame, node=None): + """Yield or write into the frame buffer.""" + if frame.buffer is None: + self.writeline("yield ", node) + else: + self.writeline("%s.append(" % frame.buffer, node) + + def end_write(self, frame): + """End the writing process started by `start_write`.""" + if frame.buffer is not None: + self.write(")") + + def simple_write(self, s, frame, node=None): + """Simple shortcut for start_write + write + end_write.""" + self.start_write(frame, node) + self.write(s) + self.end_write(frame) + + def blockvisit(self, nodes, frame): + """Visit a list of nodes as block in a frame. If the current frame + is no buffer a dummy ``if 0: yield None`` is written automatically. + """ + try: + self.writeline("pass") + for node in nodes: + self.visit(node, frame) + except CompilerExit: + pass + + def write(self, x): + """Write a string into the output stream.""" + if self._new_lines: + if not self._first_write: + self.stream.write("\n" * self._new_lines) + self.code_lineno += self._new_lines + if self._write_debug_info is not None: + self.debug_info.append((self._write_debug_info, self.code_lineno)) + self._write_debug_info = None + self._first_write = False + self.stream.write(" " * self._indentation) + self._new_lines = 0 + self.stream.write(x) + + def writeline(self, x, node=None, extra=0): + """Combination of newline and write.""" + self.newline(node, extra) + self.write(x) + + def newline(self, node=None, extra=0): + """Add one or more newlines before the next write.""" + self._new_lines = max(self._new_lines, 1 + extra) + if node is not None and node.lineno != self._last_line: + self._write_debug_info = node.lineno + self._last_line = node.lineno + + def signature(self, node, frame, extra_kwargs=None): + """Writes a function call to the stream for the current node. + A leading comma is added automatically. The extra keyword + arguments may not include python keywords otherwise a syntax + error could occur. The extra keyword arguments should be given + as python dict. + """ + # if any of the given keyword arguments is a python keyword + # we have to make sure that no invalid call is created. + kwarg_workaround = False + for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()): + if is_python_keyword(kwarg): + kwarg_workaround = True + break + + for arg in node.args: + self.write(", ") + self.visit(arg, frame) + + if not kwarg_workaround: + for kwarg in node.kwargs: + self.write(", ") + self.visit(kwarg, frame) + if extra_kwargs is not None: + for key, value in iteritems(extra_kwargs): + self.write(", %s=%s" % (key, value)) + if node.dyn_args: + self.write(", *") + self.visit(node.dyn_args, frame) + + if kwarg_workaround: + if node.dyn_kwargs is not None: + self.write(", **dict({") + else: + self.write(", **{") + for kwarg in node.kwargs: + self.write("%r: " % kwarg.key) + self.visit(kwarg.value, frame) + self.write(", ") + if extra_kwargs is not None: + for key, value in iteritems(extra_kwargs): + self.write("%r: %s, " % (key, value)) + if node.dyn_kwargs is not None: + self.write("}, **") + self.visit(node.dyn_kwargs, frame) + self.write(")") + else: + self.write("}") + + elif node.dyn_kwargs is not None: + self.write(", **") + self.visit(node.dyn_kwargs, frame) + + def pull_dependencies(self, nodes): + """Pull all the dependencies.""" + visitor = DependencyFinderVisitor() + for node in nodes: + visitor.visit(node) + for dependency in "filters", "tests": + mapping = getattr(self, dependency) + for name in getattr(visitor, dependency): + if name not in mapping: + mapping[name] = self.temporary_identifier() + self.writeline( + "%s = environment.%s[%r]" % (mapping[name], dependency, name) + ) + + def enter_frame(self, frame): + undefs = [] + for target, (action, param) in iteritems(frame.symbols.loads): + if action == VAR_LOAD_PARAMETER: + pass + elif action == VAR_LOAD_RESOLVE: + self.writeline("%s = %s(%r)" % (target, self.get_resolve_func(), param)) + elif action == VAR_LOAD_ALIAS: + self.writeline("%s = %s" % (target, param)) + elif action == VAR_LOAD_UNDEFINED: + undefs.append(target) + else: + raise NotImplementedError("unknown load instruction") + if undefs: + self.writeline("%s = missing" % " = ".join(undefs)) + + def leave_frame(self, frame, with_python_scope=False): + if not with_python_scope: + undefs = [] + for target, _ in iteritems(frame.symbols.loads): + undefs.append(target) + if undefs: + self.writeline("%s = missing" % " = ".join(undefs)) + + def func(self, name): + if self.environment.is_async: + return "async def %s" % name + return "def %s" % name + + def macro_body(self, node, frame): + """Dump the function def of a macro or call block.""" + frame = frame.inner() + frame.symbols.analyze_node(node) + macro_ref = MacroRef(node) + + explicit_caller = None + skip_special_params = set() + args = [] + for idx, arg in enumerate(node.args): + if arg.name == "caller": + explicit_caller = idx + if arg.name in ("kwargs", "varargs"): + skip_special_params.add(arg.name) + args.append(frame.symbols.ref(arg.name)) + + undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs")) + + if "caller" in undeclared: + # In older Jinja versions there was a bug that allowed caller + # to retain the special behavior even if it was mentioned in + # the argument list. However thankfully this was only really + # working if it was the last argument. So we are explicitly + # checking this now and error out if it is anywhere else in + # the argument list. + if explicit_caller is not None: + try: + node.defaults[explicit_caller - len(node.args)] + except IndexError: + self.fail( + "When defining macros or call blocks the " + 'special "caller" argument must be omitted ' + "or be given a default.", + node.lineno, + ) + else: + args.append(frame.symbols.declare_parameter("caller")) + macro_ref.accesses_caller = True + if "kwargs" in undeclared and "kwargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("kwargs")) + macro_ref.accesses_kwargs = True + if "varargs" in undeclared and "varargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("varargs")) + macro_ref.accesses_varargs = True + + # macros are delayed, they never require output checks + frame.require_output_check = False + frame.symbols.analyze_node(node) + self.writeline("%s(%s):" % (self.func("macro"), ", ".join(args)), node) + self.indent() + + self.buffer(frame) + self.enter_frame(frame) + + self.push_parameter_definitions(frame) + for idx, arg in enumerate(node.args): + ref = frame.symbols.ref(arg.name) + self.writeline("if %s is missing:" % ref) + self.indent() + try: + default = node.defaults[idx - len(node.args)] + except IndexError: + self.writeline( + "%s = undefined(%r, name=%r)" + % (ref, "parameter %r was not provided" % arg.name, arg.name) + ) + else: + self.writeline("%s = " % ref) + self.visit(default, frame) + self.mark_parameter_stored(ref) + self.outdent() + self.pop_parameter_definitions() + + self.blockvisit(node.body, frame) + self.return_buffer_contents(frame, force_unescaped=True) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + return frame, macro_ref + + def macro_def(self, macro_ref, frame): + """Dump the macro definition for the def created by macro_body.""" + arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args) + name = getattr(macro_ref.node, "name", None) + if len(macro_ref.node.args) == 1: + arg_tuple += "," + self.write( + "Macro(environment, macro, %r, (%s), %r, %r, %r, " + "context.eval_ctx.autoescape)" + % ( + name, + arg_tuple, + macro_ref.accesses_kwargs, + macro_ref.accesses_varargs, + macro_ref.accesses_caller, + ) + ) + + def position(self, node): + """Return a human readable position for the node.""" + rv = "line %d" % node.lineno + if self.name is not None: + rv += " in " + repr(self.name) + return rv + + def dump_local_context(self, frame): + return "{%s}" % ", ".join( + "%r: %s" % (name, target) + for name, target in iteritems(frame.symbols.dump_stores()) + ) + + def write_commons(self): + """Writes a common preamble that is used by root and block functions. + Primarily this sets up common local helpers and enforces a generator + through a dead branch. + """ + self.writeline("resolve = context.resolve_or_missing") + self.writeline("undefined = environment.undefined") + # always use the standard Undefined class for the implicit else of + # conditional expressions + self.writeline("cond_expr_undefined = Undefined") + self.writeline("if 0: yield None") + + def push_parameter_definitions(self, frame): + """Pushes all parameter targets from the given frame into a local + stack that permits tracking of yet to be assigned parameters. In + particular this enables the optimization from `visit_Name` to skip + undefined expressions for parameters in macros as macros can reference + otherwise unbound parameters. + """ + self._param_def_block.append(frame.symbols.dump_param_targets()) + + def pop_parameter_definitions(self): + """Pops the current parameter definitions set.""" + self._param_def_block.pop() + + def mark_parameter_stored(self, target): + """Marks a parameter in the current parameter definitions as stored. + This will skip the enforced undefined checks. + """ + if self._param_def_block: + self._param_def_block[-1].discard(target) + + def push_context_reference(self, target): + self._context_reference_stack.append(target) + + def pop_context_reference(self): + self._context_reference_stack.pop() + + def get_context_ref(self): + return self._context_reference_stack[-1] + + def get_resolve_func(self): + target = self._context_reference_stack[-1] + if target == "context": + return "resolve" + return "%s.resolve" % target + + def derive_context(self, frame): + return "%s.derived(%s)" % ( + self.get_context_ref(), + self.dump_local_context(frame), + ) + + def parameter_is_undeclared(self, target): + """Checks if a given target is an undeclared parameter.""" + if not self._param_def_block: + return False + return target in self._param_def_block[-1] + + def push_assign_tracking(self): + """Pushes a new layer for assignment tracking.""" + self._assign_stack.append(set()) + + def pop_assign_tracking(self, frame): + """Pops the topmost level for assignment tracking and updates the + context variables if necessary. + """ + vars = self._assign_stack.pop() + if not frame.toplevel or not vars: + return + public_names = [x for x in vars if x[:1] != "_"] + if len(vars) == 1: + name = next(iter(vars)) + ref = frame.symbols.ref(name) + self.writeline("context.vars[%r] = %s" % (name, ref)) + else: + self.writeline("context.vars.update({") + for idx, name in enumerate(vars): + if idx: + self.write(", ") + ref = frame.symbols.ref(name) + self.write("%r: %s" % (name, ref)) + self.write("})") + if public_names: + if len(public_names) == 1: + self.writeline("context.exported_vars.add(%r)" % public_names[0]) + else: + self.writeline( + "context.exported_vars.update((%s))" + % ", ".join(imap(repr, public_names)) + ) + + # -- Statement Visitors + + def visit_Template(self, node, frame=None): + assert frame is None, "no root frame allowed" + eval_ctx = EvalContext(self.environment, self.name) + + from .runtime import exported + + self.writeline("from __future__ import %s" % ", ".join(code_features)) + self.writeline("from jinja2.runtime import " + ", ".join(exported)) + + if self.environment.is_async: + self.writeline( + "from jinja2.asyncsupport import auto_await, " + "auto_aiter, AsyncLoopContext" + ) + + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = not self.defer_init and ", environment=environment" or "" + + # do we have an extends tag at all? If not, we can save some + # overhead by just not processing any inheritance code. + have_extends = node.find(nodes.Extends) is not None + + # find all blocks + for block in node.find_all(nodes.Block): + if block.name in self.blocks: + self.fail("block %r defined twice" % block.name, block.lineno) + self.blocks[block.name] = block + + # find all imports and import them + for import_ in node.find_all(nodes.ImportedName): + if import_.importname not in self.import_aliases: + imp = import_.importname + self.import_aliases[imp] = alias = self.temporary_identifier() + if "." in imp: + module, obj = imp.rsplit(".", 1) + self.writeline("from %s import %s as %s" % (module, obj, alias)) + else: + self.writeline("import %s as %s" % (imp, alias)) + + # add the load name + self.writeline("name = %r" % self.name) + + # generate the root render function. + self.writeline( + "%s(context, missing=missing%s):" % (self.func("root"), envenv), extra=1 + ) + self.indent() + self.write_commons() + + # process the root + frame = Frame(eval_ctx) + if "self" in find_undeclared(node.body, ("self",)): + ref = frame.symbols.declare_parameter("self") + self.writeline("%s = TemplateReference(context)" % ref) + frame.symbols.analyze_node(node) + frame.toplevel = frame.rootlevel = True + frame.require_output_check = have_extends and not self.has_known_extends + if have_extends: + self.writeline("parent_template = None") + self.enter_frame(frame) + self.pull_dependencies(node.body) + self.blockvisit(node.body, frame) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + # make sure that the parent root is called. + if have_extends: + if not self.has_known_extends: + self.indent() + self.writeline("if parent_template is not None:") + self.indent() + if supports_yield_from and not self.environment.is_async: + self.writeline("yield from parent_template.root_render_func(context)") + else: + self.writeline( + "%sfor event in parent_template." + "root_render_func(context):" + % (self.environment.is_async and "async " or "") + ) + self.indent() + self.writeline("yield event") + self.outdent() + self.outdent(1 + (not self.has_known_extends)) + + # at this point we now have the blocks collected and can visit them too. + for name, block in iteritems(self.blocks): + self.writeline( + "%s(context, missing=missing%s):" + % (self.func("block_" + name), envenv), + block, + 1, + ) + self.indent() + self.write_commons() + # It's important that we do not make this frame a child of the + # toplevel template. This would cause a variety of + # interesting issues with identifier tracking. + block_frame = Frame(eval_ctx) + undeclared = find_undeclared(block.body, ("self", "super")) + if "self" in undeclared: + ref = block_frame.symbols.declare_parameter("self") + self.writeline("%s = TemplateReference(context)" % ref) + if "super" in undeclared: + ref = block_frame.symbols.declare_parameter("super") + self.writeline("%s = context.super(%r, block_%s)" % (ref, name, name)) + block_frame.symbols.analyze_node(block) + block_frame.block = name + self.enter_frame(block_frame) + self.pull_dependencies(block.body) + self.blockvisit(block.body, block_frame) + self.leave_frame(block_frame, with_python_scope=True) + self.outdent() + + self.writeline( + "blocks = {%s}" % ", ".join("%r: block_%s" % (x, x) for x in self.blocks), + extra=1, + ) + + # add a function that returns the debug info + self.writeline( + "debug_info = %r" % "&".join("%s=%s" % x for x in self.debug_info) + ) + + def visit_Block(self, node, frame): + """Call a block and register it for the template.""" + level = 0 + if frame.toplevel: + # if we know that we are a child template, there is no need to + # check if we are one + if self.has_known_extends: + return + if self.extends_so_far > 0: + self.writeline("if parent_template is None:") + self.indent() + level += 1 + + if node.scoped: + context = self.derive_context(frame) + else: + context = self.get_context_ref() + + if ( + supports_yield_from + and not self.environment.is_async + and frame.buffer is None + ): + self.writeline( + "yield from context.blocks[%r][0](%s)" % (node.name, context), node + ) + else: + loop = self.environment.is_async and "async for" or "for" + self.writeline( + "%s event in context.blocks[%r][0](%s):" % (loop, node.name, context), + node, + ) + self.indent() + self.simple_write("event", frame) + self.outdent() + + self.outdent(level) + + def visit_Extends(self, node, frame): + """Calls the extender.""" + if not frame.toplevel: + self.fail("cannot use extend from a non top-level scope", node.lineno) + + # if the number of extends statements in general is zero so + # far, we don't have to add a check if something extended + # the template before this one. + if self.extends_so_far > 0: + + # if we have a known extends we just add a template runtime + # error into the generated code. We could catch that at compile + # time too, but i welcome it not to confuse users by throwing the + # same error at different times just "because we can". + if not self.has_known_extends: + self.writeline("if parent_template is not None:") + self.indent() + self.writeline("raise TemplateRuntimeError(%r)" % "extended multiple times") + + # if we have a known extends already we don't need that code here + # as we know that the template execution will end here. + if self.has_known_extends: + raise CompilerExit() + else: + self.outdent() + + self.writeline("parent_template = environment.get_template(", node) + self.visit(node.template, frame) + self.write(", %r)" % self.name) + self.writeline( + "for name, parent_block in parent_template.blocks.%s():" % dict_item_iter + ) + self.indent() + self.writeline("context.blocks.setdefault(name, []).append(parent_block)") + self.outdent() + + # if this extends statement was in the root level we can take + # advantage of that information and simplify the generated code + # in the top level from this point onwards + if frame.rootlevel: + self.has_known_extends = True + + # and now we have one more + self.extends_so_far += 1 + + def visit_Include(self, node, frame): + """Handles includes.""" + if node.ignore_missing: + self.writeline("try:") + self.indent() + + func_name = "get_or_select_template" + if isinstance(node.template, nodes.Const): + if isinstance(node.template.value, string_types): + func_name = "get_template" + elif isinstance(node.template.value, (tuple, list)): + func_name = "select_template" + elif isinstance(node.template, (nodes.Tuple, nodes.List)): + func_name = "select_template" + + self.writeline("template = environment.%s(" % func_name, node) + self.visit(node.template, frame) + self.write(", %r)" % self.name) + if node.ignore_missing: + self.outdent() + self.writeline("except TemplateNotFound:") + self.indent() + self.writeline("pass") + self.outdent() + self.writeline("else:") + self.indent() + + skip_event_yield = False + if node.with_context: + loop = self.environment.is_async and "async for" or "for" + self.writeline( + "%s event in template.root_render_func(" + "template.new_context(context.get_all(), True, " + "%s)):" % (loop, self.dump_local_context(frame)) + ) + elif self.environment.is_async: + self.writeline( + "for event in (await " + "template._get_default_module_async())" + "._body_stream:" + ) + else: + if supports_yield_from: + self.writeline("yield from template._get_default_module()._body_stream") + skip_event_yield = True + else: + self.writeline( + "for event in template._get_default_module()._body_stream:" + ) + + if not skip_event_yield: + self.indent() + self.simple_write("event", frame) + self.outdent() + + if node.ignore_missing: + self.outdent() + + def visit_Import(self, node, frame): + """Visit regular imports.""" + self.writeline("%s = " % frame.symbols.ref(node.target), node) + if frame.toplevel: + self.write("context.vars[%r] = " % node.target) + if self.environment.is_async: + self.write("await ") + self.write("environment.get_template(") + self.visit(node.template, frame) + self.write(", %r)." % self.name) + if node.with_context: + self.write( + "make_module%s(context.get_all(), True, %s)" + % ( + self.environment.is_async and "_async" or "", + self.dump_local_context(frame), + ) + ) + elif self.environment.is_async: + self.write("_get_default_module_async()") + else: + self.write("_get_default_module()") + if frame.toplevel and not node.target.startswith("_"): + self.writeline("context.exported_vars.discard(%r)" % node.target) + + def visit_FromImport(self, node, frame): + """Visit named imports.""" + self.newline(node) + self.write( + "included_template = %senvironment.get_template(" + % (self.environment.is_async and "await " or "") + ) + self.visit(node.template, frame) + self.write(", %r)." % self.name) + if node.with_context: + self.write( + "make_module%s(context.get_all(), True, %s)" + % ( + self.environment.is_async and "_async" or "", + self.dump_local_context(frame), + ) + ) + elif self.environment.is_async: + self.write("_get_default_module_async()") + else: + self.write("_get_default_module()") + + var_names = [] + discarded_names = [] + for name in node.names: + if isinstance(name, tuple): + name, alias = name + else: + alias = name + self.writeline( + "%s = getattr(included_template, " + "%r, missing)" % (frame.symbols.ref(alias), name) + ) + self.writeline("if %s is missing:" % frame.symbols.ref(alias)) + self.indent() + self.writeline( + "%s = undefined(%r %% " + "included_template.__name__, " + "name=%r)" + % ( + frame.symbols.ref(alias), + "the template %%r (imported on %s) does " + "not export the requested name %s" + % (self.position(node), repr(name)), + name, + ) + ) + self.outdent() + if frame.toplevel: + var_names.append(alias) + if not alias.startswith("_"): + discarded_names.append(alias) + + if var_names: + if len(var_names) == 1: + name = var_names[0] + self.writeline( + "context.vars[%r] = %s" % (name, frame.symbols.ref(name)) + ) + else: + self.writeline( + "context.vars.update({%s})" + % ", ".join( + "%r: %s" % (name, frame.symbols.ref(name)) for name in var_names + ) + ) + if discarded_names: + if len(discarded_names) == 1: + self.writeline("context.exported_vars.discard(%r)" % discarded_names[0]) + else: + self.writeline( + "context.exported_vars.difference_" + "update((%s))" % ", ".join(imap(repr, discarded_names)) + ) + + def visit_For(self, node, frame): + loop_frame = frame.inner() + test_frame = frame.inner() + else_frame = frame.inner() + + # try to figure out if we have an extended loop. An extended loop + # is necessary if the loop is in recursive mode if the special loop + # variable is accessed in the body. + extended_loop = node.recursive or "loop" in find_undeclared( + node.iter_child_nodes(only=("body",)), ("loop",) + ) + + loop_ref = None + if extended_loop: + loop_ref = loop_frame.symbols.declare_parameter("loop") + + loop_frame.symbols.analyze_node(node, for_branch="body") + if node.else_: + else_frame.symbols.analyze_node(node, for_branch="else") + + if node.test: + loop_filter_func = self.temporary_identifier() + test_frame.symbols.analyze_node(node, for_branch="test") + self.writeline("%s(fiter):" % self.func(loop_filter_func), node.test) + self.indent() + self.enter_frame(test_frame) + self.writeline(self.environment.is_async and "async for " or "for ") + self.visit(node.target, loop_frame) + self.write(" in ") + self.write(self.environment.is_async and "auto_aiter(fiter)" or "fiter") + self.write(":") + self.indent() + self.writeline("if ", node.test) + self.visit(node.test, test_frame) + self.write(":") + self.indent() + self.writeline("yield ") + self.visit(node.target, loop_frame) + self.outdent(3) + self.leave_frame(test_frame, with_python_scope=True) + + # if we don't have an recursive loop we have to find the shadowed + # variables at that point. Because loops can be nested but the loop + # variable is a special one we have to enforce aliasing for it. + if node.recursive: + self.writeline( + "%s(reciter, loop_render_func, depth=0):" % self.func("loop"), node + ) + self.indent() + self.buffer(loop_frame) + + # Use the same buffer for the else frame + else_frame.buffer = loop_frame.buffer + + # make sure the loop variable is a special one and raise a template + # assertion error if a loop tries to write to loop + if extended_loop: + self.writeline("%s = missing" % loop_ref) + + for name in node.find_all(nodes.Name): + if name.ctx == "store" and name.name == "loop": + self.fail( + "Can't assign to special loop variable in for-loop target", + name.lineno, + ) + + if node.else_: + iteration_indicator = self.temporary_identifier() + self.writeline("%s = 1" % iteration_indicator) + + self.writeline(self.environment.is_async and "async for " or "for ", node) + self.visit(node.target, loop_frame) + if extended_loop: + if self.environment.is_async: + self.write(", %s in AsyncLoopContext(" % loop_ref) + else: + self.write(", %s in LoopContext(" % loop_ref) + else: + self.write(" in ") + + if node.test: + self.write("%s(" % loop_filter_func) + if node.recursive: + self.write("reciter") + else: + if self.environment.is_async and not extended_loop: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async and not extended_loop: + self.write(")") + if node.test: + self.write(")") + + if node.recursive: + self.write(", undefined, loop_render_func, depth):") + else: + self.write(extended_loop and ", undefined):" or ":") + + self.indent() + self.enter_frame(loop_frame) + + self.blockvisit(node.body, loop_frame) + if node.else_: + self.writeline("%s = 0" % iteration_indicator) + self.outdent() + self.leave_frame( + loop_frame, with_python_scope=node.recursive and not node.else_ + ) + + if node.else_: + self.writeline("if %s:" % iteration_indicator) + self.indent() + self.enter_frame(else_frame) + self.blockvisit(node.else_, else_frame) + self.leave_frame(else_frame) + self.outdent() + + # if the node was recursive we have to return the buffer contents + # and start the iteration code + if node.recursive: + self.return_buffer_contents(loop_frame) + self.outdent() + self.start_write(frame, node) + if self.environment.is_async: + self.write("await ") + self.write("loop(") + if self.environment.is_async: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async: + self.write(")") + self.write(", loop)") + self.end_write(frame) + + def visit_If(self, node, frame): + if_frame = frame.soft() + self.writeline("if ", node) + self.visit(node.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(node.body, if_frame) + self.outdent() + for elif_ in node.elif_: + self.writeline("elif ", elif_) + self.visit(elif_.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(elif_.body, if_frame) + self.outdent() + if node.else_: + self.writeline("else:") + self.indent() + self.blockvisit(node.else_, if_frame) + self.outdent() + + def visit_Macro(self, node, frame): + macro_frame, macro_ref = self.macro_body(node, frame) + self.newline() + if frame.toplevel: + if not node.name.startswith("_"): + self.write("context.exported_vars.add(%r)" % node.name) + self.writeline("context.vars[%r] = " % node.name) + self.write("%s = " % frame.symbols.ref(node.name)) + self.macro_def(macro_ref, macro_frame) + + def visit_CallBlock(self, node, frame): + call_frame, macro_ref = self.macro_body(node, frame) + self.writeline("caller = ") + self.macro_def(macro_ref, call_frame) + self.start_write(frame, node) + self.visit_Call(node.call, frame, forward_caller=True) + self.end_write(frame) + + def visit_FilterBlock(self, node, frame): + filter_frame = frame.inner() + filter_frame.symbols.analyze_node(node) + self.enter_frame(filter_frame) + self.buffer(filter_frame) + self.blockvisit(node.body, filter_frame) + self.start_write(frame, node) + self.visit_Filter(node.filter, filter_frame) + self.end_write(frame) + self.leave_frame(filter_frame) + + def visit_With(self, node, frame): + with_frame = frame.inner() + with_frame.symbols.analyze_node(node) + self.enter_frame(with_frame) + for target, expr in izip(node.targets, node.values): + self.newline() + self.visit(target, with_frame) + self.write(" = ") + self.visit(expr, frame) + self.blockvisit(node.body, with_frame) + self.leave_frame(with_frame) + + def visit_ExprStmt(self, node, frame): + self.newline(node) + self.visit(node.node, frame) + + _FinalizeInfo = namedtuple("_FinalizeInfo", ("const", "src")) + #: The default finalize function if the environment isn't configured + #: with one. Or if the environment has one, this is called on that + #: function's output for constants. + _default_finalize = text_type + _finalize = None + + def _make_finalize(self): + """Build the finalize function to be used on constants and at + runtime. Cached so it's only created once for all output nodes. + + Returns a ``namedtuple`` with the following attributes: + + ``const`` + A function to finalize constant data at compile time. + + ``src`` + Source code to output around nodes to be evaluated at + runtime. + """ + if self._finalize is not None: + return self._finalize + + finalize = default = self._default_finalize + src = None + + if self.environment.finalize: + src = "environment.finalize(" + env_finalize = self.environment.finalize + + def finalize(value): + return default(env_finalize(value)) + + if getattr(env_finalize, "contextfunction", False) is True: + src += "context, " + finalize = None # noqa: F811 + elif getattr(env_finalize, "evalcontextfunction", False) is True: + src += "context.eval_ctx, " + finalize = None + elif getattr(env_finalize, "environmentfunction", False) is True: + src += "environment, " + + def finalize(value): + return default(env_finalize(self.environment, value)) + + self._finalize = self._FinalizeInfo(finalize, src) + return self._finalize + + def _output_const_repr(self, group): + """Given a group of constant values converted from ``Output`` + child nodes, produce a string to write to the template module + source. + """ + return repr(concat(group)) + + def _output_child_to_const(self, node, frame, finalize): + """Try to optimize a child of an ``Output`` node by trying to + convert it to constant, finalized data at compile time. + + If :exc:`Impossible` is raised, the node is not constant and + will be evaluated at runtime. Any other exception will also be + evaluated at runtime for easier debugging. + """ + const = node.as_const(frame.eval_ctx) + + if frame.eval_ctx.autoescape: + const = escape(const) + + # Template data doesn't go through finalize. + if isinstance(node, nodes.TemplateData): + return text_type(const) + + return finalize.const(const) + + def _output_child_pre(self, node, frame, finalize): + """Output extra source code before visiting a child of an + ``Output`` node. + """ + if frame.eval_ctx.volatile: + self.write("(escape if context.eval_ctx.autoescape else to_string)(") + elif frame.eval_ctx.autoescape: + self.write("escape(") + else: + self.write("to_string(") + + if finalize.src is not None: + self.write(finalize.src) + + def _output_child_post(self, node, frame, finalize): + """Output extra source code after visiting a child of an + ``Output`` node. + """ + self.write(")") + + if finalize.src is not None: + self.write(")") + + def visit_Output(self, node, frame): + # If an extends is active, don't render outside a block. + if frame.require_output_check: + # A top-level extends is known to exist at compile time. + if self.has_known_extends: + return + + self.writeline("if parent_template is None:") + self.indent() + + finalize = self._make_finalize() + body = [] + + # Evaluate constants at compile time if possible. Each item in + # body will be either a list of static data or a node to be + # evaluated at runtime. + for child in node.nodes: + try: + if not ( + # If the finalize function requires runtime context, + # constants can't be evaluated at compile time. + finalize.const + # Unless it's basic template data that won't be + # finalized anyway. + or isinstance(child, nodes.TemplateData) + ): + raise nodes.Impossible() + + const = self._output_child_to_const(child, frame, finalize) + except (nodes.Impossible, Exception): + # The node was not constant and needs to be evaluated at + # runtime. Or another error was raised, which is easier + # to debug at runtime. + body.append(child) + continue + + if body and isinstance(body[-1], list): + body[-1].append(const) + else: + body.append([const]) + + if frame.buffer is not None: + if len(body) == 1: + self.writeline("%s.append(" % frame.buffer) + else: + self.writeline("%s.extend((" % frame.buffer) + + self.indent() + + for item in body: + if isinstance(item, list): + # A group of constant data to join and output. + val = self._output_const_repr(item) + + if frame.buffer is None: + self.writeline("yield " + val) + else: + self.writeline(val + ",") + else: + if frame.buffer is None: + self.writeline("yield ", item) + else: + self.newline(item) + + # A node to be evaluated at runtime. + self._output_child_pre(item, frame, finalize) + self.visit(item, frame) + self._output_child_post(item, frame, finalize) + + if frame.buffer is not None: + self.write(",") + + if frame.buffer is not None: + self.outdent() + self.writeline(")" if len(body) == 1 else "))") + + if frame.require_output_check: + self.outdent() + + def visit_Assign(self, node, frame): + self.push_assign_tracking() + self.newline(node) + self.visit(node.target, frame) + self.write(" = ") + self.visit(node.node, frame) + self.pop_assign_tracking(frame) + + def visit_AssignBlock(self, node, frame): + self.push_assign_tracking() + block_frame = frame.inner() + # This is a special case. Since a set block always captures we + # will disable output checks. This way one can use set blocks + # toplevel even in extended templates. + block_frame.require_output_check = False + block_frame.symbols.analyze_node(node) + self.enter_frame(block_frame) + self.buffer(block_frame) + self.blockvisit(node.body, block_frame) + self.newline(node) + self.visit(node.target, frame) + self.write(" = (Markup if context.eval_ctx.autoescape else identity)(") + if node.filter is not None: + self.visit_Filter(node.filter, block_frame) + else: + self.write("concat(%s)" % block_frame.buffer) + self.write(")") + self.pop_assign_tracking(frame) + self.leave_frame(block_frame) + + # -- Expression Visitors + + def visit_Name(self, node, frame): + if node.ctx == "store" and frame.toplevel: + if self._assign_stack: + self._assign_stack[-1].add(node.name) + ref = frame.symbols.ref(node.name) + + # If we are looking up a variable we might have to deal with the + # case where it's undefined. We can skip that case if the load + # instruction indicates a parameter which are always defined. + if node.ctx == "load": + load = frame.symbols.find_load(ref) + if not ( + load is not None + and load[0] == VAR_LOAD_PARAMETER + and not self.parameter_is_undeclared(ref) + ): + self.write( + "(undefined(name=%r) if %s is missing else %s)" + % (node.name, ref, ref) + ) + return + + self.write(ref) + + def visit_NSRef(self, node, frame): + # NSRefs can only be used to store values; since they use the normal + # `foo.bar` notation they will be parsed as a normal attribute access + # when used anywhere but in a `set` context + ref = frame.symbols.ref(node.name) + self.writeline("if not isinstance(%s, Namespace):" % ref) + self.indent() + self.writeline( + "raise TemplateRuntimeError(%r)" + % "cannot assign attribute on non-namespace object" + ) + self.outdent() + self.writeline("%s[%r]" % (ref, node.attr)) + + def visit_Const(self, node, frame): + val = node.as_const(frame.eval_ctx) + if isinstance(val, float): + self.write(str(val)) + else: + self.write(repr(val)) + + def visit_TemplateData(self, node, frame): + try: + self.write(repr(node.as_const(frame.eval_ctx))) + except nodes.Impossible: + self.write( + "(Markup if context.eval_ctx.autoescape else identity)(%r)" % node.data + ) + + def visit_Tuple(self, node, frame): + self.write("(") + idx = -1 + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write(idx == 0 and ",)" or ")") + + def visit_List(self, node, frame): + self.write("[") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write("]") + + def visit_Dict(self, node, frame): + self.write("{") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item.key, frame) + self.write(": ") + self.visit(item.value, frame) + self.write("}") + + def binop(operator, interceptable=True): # noqa: B902 + @optimizeconst + def visitor(self, node, frame): + if ( + self.environment.sandboxed + and operator in self.environment.intercepted_binops + ): + self.write("environment.call_binop(context, %r, " % operator) + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(" %s " % operator) + self.visit(node.right, frame) + self.write(")") + + return visitor + + def uaop(operator, interceptable=True): # noqa: B902 + @optimizeconst + def visitor(self, node, frame): + if ( + self.environment.sandboxed + and operator in self.environment.intercepted_unops + ): + self.write("environment.call_unop(context, %r, " % operator) + self.visit(node.node, frame) + else: + self.write("(" + operator) + self.visit(node.node, frame) + self.write(")") + + return visitor + + visit_Add = binop("+") + visit_Sub = binop("-") + visit_Mul = binop("*") + visit_Div = binop("/") + visit_FloorDiv = binop("//") + visit_Pow = binop("**") + visit_Mod = binop("%") + visit_And = binop("and", interceptable=False) + visit_Or = binop("or", interceptable=False) + visit_Pos = uaop("+") + visit_Neg = uaop("-") + visit_Not = uaop("not ", interceptable=False) + del binop, uaop + + @optimizeconst + def visit_Concat(self, node, frame): + if frame.eval_ctx.volatile: + func_name = "(context.eval_ctx.volatile and markup_join or unicode_join)" + elif frame.eval_ctx.autoescape: + func_name = "markup_join" + else: + func_name = "unicode_join" + self.write("%s((" % func_name) + for arg in node.nodes: + self.visit(arg, frame) + self.write(", ") + self.write("))") + + @optimizeconst + def visit_Compare(self, node, frame): + self.write("(") + self.visit(node.expr, frame) + for op in node.ops: + self.visit(op, frame) + self.write(")") + + def visit_Operand(self, node, frame): + self.write(" %s " % operators[node.op]) + self.visit(node.expr, frame) + + @optimizeconst + def visit_Getattr(self, node, frame): + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getattr(") + self.visit(node.node, frame) + self.write(", %r)" % node.attr) + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Getitem(self, node, frame): + # slices bypass the environment getitem method. + if isinstance(node.arg, nodes.Slice): + self.visit(node.node, frame) + self.write("[") + self.visit(node.arg, frame) + self.write("]") + else: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getitem(") + self.visit(node.node, frame) + self.write(", ") + self.visit(node.arg, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + def visit_Slice(self, node, frame): + if node.start is not None: + self.visit(node.start, frame) + self.write(":") + if node.stop is not None: + self.visit(node.stop, frame) + if node.step is not None: + self.write(":") + self.visit(node.step, frame) + + @optimizeconst + def visit_Filter(self, node, frame): + if self.environment.is_async: + self.write("await auto_await(") + self.write(self.filters[node.name] + "(") + func = self.environment.filters.get(node.name) + if func is None: + self.fail("no filter named %r" % node.name, node.lineno) + if getattr(func, "contextfilter", False) is True: + self.write("context, ") + elif getattr(func, "evalcontextfilter", False) is True: + self.write("context.eval_ctx, ") + elif getattr(func, "environmentfilter", False) is True: + self.write("environment, ") + + # if the filter node is None we are inside a filter block + # and want to write to the current buffer + if node.node is not None: + self.visit(node.node, frame) + elif frame.eval_ctx.volatile: + self.write( + "(context.eval_ctx.autoescape and" + " Markup(concat(%s)) or concat(%s))" % (frame.buffer, frame.buffer) + ) + elif frame.eval_ctx.autoescape: + self.write("Markup(concat(%s))" % frame.buffer) + else: + self.write("concat(%s)" % frame.buffer) + self.signature(node, frame) + self.write(")") + if self.environment.is_async: + self.write(")") + + @optimizeconst + def visit_Test(self, node, frame): + self.write(self.tests[node.name] + "(") + if node.name not in self.environment.tests: + self.fail("no test named %r" % node.name, node.lineno) + self.visit(node.node, frame) + self.signature(node, frame) + self.write(")") + + @optimizeconst + def visit_CondExpr(self, node, frame): + def write_expr2(): + if node.expr2 is not None: + return self.visit(node.expr2, frame) + self.write( + "cond_expr_undefined(%r)" + % ( + "the inline if-" + "expression on %s evaluated to false and " + "no else section was defined." % self.position(node) + ) + ) + + self.write("(") + self.visit(node.expr1, frame) + self.write(" if ") + self.visit(node.test, frame) + self.write(" else ") + write_expr2() + self.write(")") + + @optimizeconst + def visit_Call(self, node, frame, forward_caller=False): + if self.environment.is_async: + self.write("await auto_await(") + if self.environment.sandboxed: + self.write("environment.call(context, ") + else: + self.write("context.call(") + self.visit(node.node, frame) + extra_kwargs = forward_caller and {"caller": "caller"} or None + self.signature(node, frame, extra_kwargs) + self.write(")") + if self.environment.is_async: + self.write(")") + + def visit_Keyword(self, node, frame): + self.write(node.key + "=") + self.visit(node.value, frame) + + # -- Unused nodes for extensions + + def visit_MarkSafe(self, node, frame): + self.write("Markup(") + self.visit(node.expr, frame) + self.write(")") + + def visit_MarkSafeIfAutoescape(self, node, frame): + self.write("(context.eval_ctx.autoescape and Markup or identity)(") + self.visit(node.expr, frame) + self.write(")") + + def visit_EnvironmentAttribute(self, node, frame): + self.write("environment." + node.name) + + def visit_ExtensionAttribute(self, node, frame): + self.write("environment.extensions[%r].%s" % (node.identifier, node.name)) + + def visit_ImportedName(self, node, frame): + self.write(self.import_aliases[node.importname]) + + def visit_InternalName(self, node, frame): + self.write(node.name) + + def visit_ContextReference(self, node, frame): + self.write("context") + + def visit_DerivedContextReference(self, node, frame): + self.write(self.derive_context(frame)) + + def visit_Continue(self, node, frame): + self.writeline("continue", node) + + def visit_Break(self, node, frame): + self.writeline("break", node) + + def visit_Scope(self, node, frame): + scope_frame = frame.inner() + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + + def visit_OverlayScope(self, node, frame): + ctx = self.temporary_identifier() + self.writeline("%s = %s" % (ctx, self.derive_context(frame))) + self.writeline("%s.vars = " % ctx) + self.visit(node.context, frame) + self.push_context_reference(ctx) + + scope_frame = frame.inner(isolated=True) + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + self.pop_context_reference() + + def visit_EvalContextModifier(self, node, frame): + for keyword in node.options: + self.writeline("context.eval_ctx.%s = " % keyword.key) + self.visit(keyword.value, frame) + try: + val = keyword.value.as_const(frame.eval_ctx) + except nodes.Impossible: + frame.eval_ctx.volatile = True + else: + setattr(frame.eval_ctx, keyword.key, val) + + def visit_ScopedEvalContextModifier(self, node, frame): + old_ctx_name = self.temporary_identifier() + saved_ctx = frame.eval_ctx.save() + self.writeline("%s = context.eval_ctx.save()" % old_ctx_name) + self.visit_EvalContextModifier(node, frame) + for child in node.body: + self.visit(child, frame) + frame.eval_ctx.revert(saved_ctx) + self.writeline("context.eval_ctx.revert(%s)" % old_ctx_name) diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/constants.py b/magma/squid_cnf/charms/squid/venv/jinja2/constants.py new file mode 100644 index 00000000..bf7f2ca7 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/constants.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +#: list of lorem ipsum words used by the lipsum() helper function +LOREM_IPSUM_WORDS = u"""\ +a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at +auctor augue bibendum blandit class commodo condimentum congue consectetuer +consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus +diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend +elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames +faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac +hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum +justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem +luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie +mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non +nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque +penatibus per pharetra phasellus placerat platea porta porttitor posuere +potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus +ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit +sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor +tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices +ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus +viverra volutpat vulputate""" diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/debug.py b/magma/squid_cnf/charms/squid/venv/jinja2/debug.py new file mode 100644 index 00000000..5d8aec31 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/debug.py @@ -0,0 +1,268 @@ +import sys +from types import CodeType + +from . import TemplateSyntaxError +from ._compat import PYPY +from .utils import internal_code +from .utils import missing + + +def rewrite_traceback_stack(source=None): + """Rewrite the current exception to replace any tracebacks from + within compiled template code with tracebacks that look like they + came from the template source. + + This must be called within an ``except`` block. + + :param exc_info: A :meth:`sys.exc_info` tuple. If not provided, + the current ``exc_info`` is used. + :param source: For ``TemplateSyntaxError``, the original source if + known. + :return: A :meth:`sys.exc_info` tuple that can be re-raised. + """ + exc_type, exc_value, tb = sys.exc_info() + + if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated: + exc_value.translated = True + exc_value.source = source + + try: + # Remove the old traceback on Python 3, otherwise the frames + # from the compiler still show up. + exc_value.with_traceback(None) + except AttributeError: + pass + + # Outside of runtime, so the frame isn't executing template + # code, but it still needs to point at the template. + tb = fake_traceback( + exc_value, None, exc_value.filename or "", exc_value.lineno + ) + else: + # Skip the frame for the render function. + tb = tb.tb_next + + stack = [] + + # Build the stack of traceback object, replacing any in template + # code with the source file and line information. + while tb is not None: + # Skip frames decorated with @internalcode. These are internal + # calls that aren't useful in template debugging output. + if tb.tb_frame.f_code in internal_code: + tb = tb.tb_next + continue + + template = tb.tb_frame.f_globals.get("__jinja_template__") + + if template is not None: + lineno = template.get_corresponding_lineno(tb.tb_lineno) + fake_tb = fake_traceback(exc_value, tb, template.filename, lineno) + stack.append(fake_tb) + else: + stack.append(tb) + + tb = tb.tb_next + + tb_next = None + + # Assign tb_next in reverse to avoid circular references. + for tb in reversed(stack): + tb_next = tb_set_next(tb, tb_next) + + return exc_type, exc_value, tb_next + + +def fake_traceback(exc_value, tb, filename, lineno): + """Produce a new traceback object that looks like it came from the + template source instead of the compiled code. The filename, line + number, and location name will point to the template, and the local + variables will be the current template context. + + :param exc_value: The original exception to be re-raised to create + the new traceback. + :param tb: The original traceback to get the local variables and + code info from. + :param filename: The template filename. + :param lineno: The line number in the template source. + """ + if tb is not None: + # Replace the real locals with the context that would be + # available at that point in the template. + locals = get_template_locals(tb.tb_frame.f_locals) + locals.pop("__jinja_exception__", None) + else: + locals = {} + + globals = { + "__name__": filename, + "__file__": filename, + "__jinja_exception__": exc_value, + } + # Raise an exception at the correct line number. + code = compile("\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec") + + # Build a new code object that points to the template file and + # replaces the location with a block name. + try: + location = "template" + + if tb is not None: + function = tb.tb_frame.f_code.co_name + + if function == "root": + location = "top-level template code" + elif function.startswith("block_"): + location = 'block "%s"' % function[6:] + + # Collect arguments for the new code object. CodeType only + # accepts positional arguments, and arguments were inserted in + # new Python versions. + code_args = [] + + for attr in ( + "argcount", + "posonlyargcount", # Python 3.8 + "kwonlyargcount", # Python 3 + "nlocals", + "stacksize", + "flags", + "code", # codestring + "consts", # constants + "names", + "varnames", + ("filename", filename), + ("name", location), + "firstlineno", + "lnotab", + "freevars", + "cellvars", + ): + if isinstance(attr, tuple): + # Replace with given value. + code_args.append(attr[1]) + continue + + try: + # Copy original value if it exists. + code_args.append(getattr(code, "co_" + attr)) + except AttributeError: + # Some arguments were added later. + continue + + code = CodeType(*code_args) + except Exception: + # Some environments such as Google App Engine don't support + # modifying code objects. + pass + + # Execute the new code, which is guaranteed to raise, and return + # the new traceback without this frame. + try: + exec(code, globals, locals) + except BaseException: + return sys.exc_info()[2].tb_next + + +def get_template_locals(real_locals): + """Based on the runtime locals, get the context that would be + available at that point in the template. + """ + # Start with the current template context. + ctx = real_locals.get("context") + + if ctx: + data = ctx.get_all().copy() + else: + data = {} + + # Might be in a derived context that only sets local variables + # rather than pushing a context. Local variables follow the scheme + # l_depth_name. Find the highest-depth local that has a value for + # each name. + local_overrides = {} + + for name, value in real_locals.items(): + if not name.startswith("l_") or value is missing: + # Not a template variable, or no longer relevant. + continue + + try: + _, depth, name = name.split("_", 2) + depth = int(depth) + except ValueError: + continue + + cur_depth = local_overrides.get(name, (-1,))[0] + + if cur_depth < depth: + local_overrides[name] = (depth, value) + + # Modify the context with any derived context. + for name, (_, value) in local_overrides.items(): + if value is missing: + data.pop(name, None) + else: + data[name] = value + + return data + + +if sys.version_info >= (3, 7): + # tb_next is directly assignable as of Python 3.7 + def tb_set_next(tb, tb_next): + tb.tb_next = tb_next + return tb + + +elif PYPY: + # PyPy might have special support, and won't work with ctypes. + try: + import tputil + except ImportError: + # Without tproxy support, use the original traceback. + def tb_set_next(tb, tb_next): + return tb + + else: + # With tproxy support, create a proxy around the traceback that + # returns the new tb_next. + def tb_set_next(tb, tb_next): + def controller(op): + if op.opname == "__getattribute__" and op.args[0] == "tb_next": + return tb_next + + return op.delegate() + + return tputil.make_proxy(controller, obj=tb) + + +else: + # Use ctypes to assign tb_next at the C level since it's read-only + # from Python. + import ctypes + + class _CTraceback(ctypes.Structure): + _fields_ = [ + # Extra PyObject slots when compiled with Py_TRACE_REFS. + ("PyObject_HEAD", ctypes.c_byte * object().__sizeof__()), + # Only care about tb_next as an object, not a traceback. + ("tb_next", ctypes.py_object), + ] + + def tb_set_next(tb, tb_next): + c_tb = _CTraceback.from_address(id(tb)) + + # Clear out the old tb_next. + if tb.tb_next is not None: + c_tb_next = ctypes.py_object(tb.tb_next) + c_tb.tb_next = ctypes.py_object() + ctypes.pythonapi.Py_DecRef(c_tb_next) + + # Assign the new tb_next. + if tb_next is not None: + c_tb_next = ctypes.py_object(tb_next) + ctypes.pythonapi.Py_IncRef(c_tb_next) + c_tb.tb_next = c_tb_next + + return tb diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/defaults.py b/magma/squid_cnf/charms/squid/venv/jinja2/defaults.py new file mode 100644 index 00000000..8e0e7d77 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/defaults.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from ._compat import range_type +from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401 +from .tests import TESTS as DEFAULT_TESTS # noqa: F401 +from .utils import Cycler +from .utils import generate_lorem_ipsum +from .utils import Joiner +from .utils import Namespace + +# defaults for the parser / lexer +BLOCK_START_STRING = "{%" +BLOCK_END_STRING = "%}" +VARIABLE_START_STRING = "{{" +VARIABLE_END_STRING = "}}" +COMMENT_START_STRING = "{#" +COMMENT_END_STRING = "#}" +LINE_STATEMENT_PREFIX = None +LINE_COMMENT_PREFIX = None +TRIM_BLOCKS = False +LSTRIP_BLOCKS = False +NEWLINE_SEQUENCE = "\n" +KEEP_TRAILING_NEWLINE = False + +# default filters, tests and namespace + +DEFAULT_NAMESPACE = { + "range": range_type, + "dict": dict, + "lipsum": generate_lorem_ipsum, + "cycler": Cycler, + "joiner": Joiner, + "namespace": Namespace, +} + +# default policies +DEFAULT_POLICIES = { + "compiler.ascii_str": True, + "urlize.rel": "noopener", + "urlize.target": None, + "truncate.leeway": 5, + "json.dumps_function": None, + "json.dumps_kwargs": {"sort_keys": True}, + "ext.i18n.trimmed": False, +} diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/environment.py b/magma/squid_cnf/charms/squid/venv/jinja2/environment.py new file mode 100644 index 00000000..8430390e --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/environment.py @@ -0,0 +1,1362 @@ +# -*- coding: utf-8 -*- +"""Classes for managing templates and their runtime and compile time +options. +""" +import os +import sys +import weakref +from functools import partial +from functools import reduce + +from markupsafe import Markup + +from . import nodes +from ._compat import encode_filename +from ._compat import implements_iterator +from ._compat import implements_to_string +from ._compat import iteritems +from ._compat import PY2 +from ._compat import PYPY +from ._compat import reraise +from ._compat import string_types +from ._compat import text_type +from .compiler import CodeGenerator +from .compiler import generate +from .defaults import BLOCK_END_STRING +from .defaults import BLOCK_START_STRING +from .defaults import COMMENT_END_STRING +from .defaults import COMMENT_START_STRING +from .defaults import DEFAULT_FILTERS +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS +from .defaults import KEEP_TRAILING_NEWLINE +from .defaults import LINE_COMMENT_PREFIX +from .defaults import LINE_STATEMENT_PREFIX +from .defaults import LSTRIP_BLOCKS +from .defaults import NEWLINE_SEQUENCE +from .defaults import TRIM_BLOCKS +from .defaults import VARIABLE_END_STRING +from .defaults import VARIABLE_START_STRING +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .lexer import get_lexer +from .lexer import TokenStream +from .nodes import EvalContext +from .parser import Parser +from .runtime import Context +from .runtime import new_context +from .runtime import Undefined +from .utils import concat +from .utils import consume +from .utils import have_async_gen +from .utils import import_string +from .utils import internalcode +from .utils import LRUCache +from .utils import missing + +# for direct template usage we have up to ten living environments +_spontaneous_environments = LRUCache(10) + + +def get_spontaneous_environment(cls, *args): + """Return a new spontaneous environment. A spontaneous environment + is used for templates created directly rather than through an + existing environment. + + :param cls: Environment class to create. + :param args: Positional arguments passed to environment. + """ + key = (cls, args) + + try: + return _spontaneous_environments[key] + except KeyError: + _spontaneous_environments[key] = env = cls(*args) + env.shared = True + return env + + +def create_cache(size): + """Return the cache class for the given size.""" + if size == 0: + return None + if size < 0: + return {} + return LRUCache(size) + + +def copy_cache(cache): + """Create an empty copy of the given cache.""" + if cache is None: + return None + elif type(cache) is dict: + return {} + return LRUCache(cache.capacity) + + +def load_extensions(environment, extensions): + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated environments. + """ + result = {} + for extension in extensions: + if isinstance(extension, string_types): + extension = import_string(extension) + result[extension.identifier] = extension(environment) + return result + + +def fail_for_missing_callable(string, name): + msg = string % name + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = "%s (%s; did you forget to quote the callable name?)" % (msg, e) + raise TemplateRuntimeError(msg) + + +def _environment_sanity_check(environment): + """Perform a sanity check on the environment.""" + assert issubclass( + environment.undefined, Undefined + ), "undefined must be a subclass of undefined because filters depend on it." + assert ( + environment.block_start_string + != environment.variable_start_string + != environment.comment_start_string + ), "block, variable and comment start strings must be different" + assert environment.newline_sequence in ( + "\r", + "\r\n", + "\n", + ), "newline_sequence set to unknown line ending string." + return environment + + +class Environment(object): + r"""The core component of Jinja is the `Environment`. It contains + important shared variables like configuration, filters, tests, + globals and others. Instances of this class may be modified if + they are not shared and if no template was loaded so far. + Modifications on environments after the first template was loaded + will lead to surprising effects and undefined behavior. + + Here are the possible initialization parameters: + + `block_start_string` + The string marking the beginning of a block. Defaults to ``'{%'``. + + `block_end_string` + The string marking the end of a block. Defaults to ``'%}'``. + + `variable_start_string` + The string marking the beginning of a print statement. + Defaults to ``'{{'``. + + `variable_end_string` + The string marking the end of a print statement. Defaults to + ``'}}'``. + + `comment_start_string` + The string marking the beginning of a comment. Defaults to ``'{#'``. + + `comment_end_string` + The string marking the end of a comment. Defaults to ``'#}'``. + + `line_statement_prefix` + If given and a string, this will be used as prefix for line based + statements. See also :ref:`line-statements`. + + `line_comment_prefix` + If given and a string, this will be used as prefix for line based + comments. See also :ref:`line-statements`. + + .. versionadded:: 2.2 + + `trim_blocks` + If this is set to ``True`` the first newline after a block is + removed (block, not variable tag!). Defaults to `False`. + + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + + `newline_sequence` + The sequence that starts a newline. Must be one of ``'\r'``, + ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a + useful default for Linux and OS X systems as well as web + applications. + + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + + `extensions` + List of Jinja extensions to use. This can either be import paths + as strings or extension classes. For more information have a + look at :ref:`the extensions documentation `. + + `optimized` + should the optimizer be enabled? Default is ``True``. + + `undefined` + :class:`Undefined` or a subclass of it that is used to represent + undefined values in the template. + + `finalize` + A callable that can be used to process the result of a variable + expression before it is output. For example one can convert + ``None`` implicitly into an empty string here. + + `autoescape` + If set to ``True`` the XML/HTML autoescaping feature is enabled by + default. For more details about autoescaping see + :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return ``True`` or ``False`` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function + + `loader` + The template loader for this environment. + + `cache_size` + The size of the cache. Per default this is ``400`` which means + that if more than 400 templates are loaded the loader will clean + out the least recently used template. If the cache size is set to + ``0`` templates are recompiled all the time, if the cache size is + ``-1`` the cache will not be cleaned. + + .. versionchanged:: 2.8 + The cache size was increased to 400 from a low 50. + + `auto_reload` + Some loaders load templates from locations where the template + sources may change (ie: file system or database). If + ``auto_reload`` is set to ``True`` (default) every time a template is + requested the loader checks if the source changed and if yes, it + will reload the template. For higher performance it's possible to + disable that. + + `bytecode_cache` + If set to a bytecode cache object, this object will provide a + cache for the internal Jinja bytecode so that templates don't + have to be parsed if they were not changed. + + See :ref:`bytecode-cache` for more information. + + `enable_async` + If set to true this enables async template execution which allows + you to take advantage of newer Python features. This requires + Python 3.6 or later. + """ + + #: if this environment is sandboxed. Modifying this variable won't make + #: the environment sandboxed though. For a real sandboxed environment + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. + sandboxed = False + + #: True if the environment is just an overlay + overlayed = False + + #: the environment this environment is linked to if it is an overlay + linked_to = None + + #: shared environments have this set to `True`. A shared environment + #: must not be modified + shared = False + + #: the class that is used for code generation. See + #: :class:`~jinja2.compiler.CodeGenerator` for more information. + code_generator_class = CodeGenerator + + #: the context class thatis used for templates. See + #: :class:`~jinja2.runtime.Context` for more information. + context_class = Context + + def __init__( + self, + block_start_string=BLOCK_START_STRING, + block_end_string=BLOCK_END_STRING, + variable_start_string=VARIABLE_START_STRING, + variable_end_string=VARIABLE_END_STRING, + comment_start_string=COMMENT_START_STRING, + comment_end_string=COMMENT_END_STRING, + line_statement_prefix=LINE_STATEMENT_PREFIX, + line_comment_prefix=LINE_COMMENT_PREFIX, + trim_blocks=TRIM_BLOCKS, + lstrip_blocks=LSTRIP_BLOCKS, + newline_sequence=NEWLINE_SEQUENCE, + keep_trailing_newline=KEEP_TRAILING_NEWLINE, + extensions=(), + optimized=True, + undefined=Undefined, + finalize=None, + autoescape=False, + loader=None, + cache_size=400, + auto_reload=True, + bytecode_cache=None, + enable_async=False, + ): + # !!Important notice!! + # The constructor accepts quite a few arguments that should be + # passed by keyword rather than position. However it's important to + # not change the order of arguments because it's used at least + # internally in those cases: + # - spontaneous environments (i18n extension and Template) + # - unittests + # If parameter changes are required only add parameters at the end + # and don't change the arguments (or the defaults!) of the arguments + # existing already. + + # lexer / parser information + self.block_start_string = block_start_string + self.block_end_string = block_end_string + self.variable_start_string = variable_start_string + self.variable_end_string = variable_end_string + self.comment_start_string = comment_start_string + self.comment_end_string = comment_end_string + self.line_statement_prefix = line_statement_prefix + self.line_comment_prefix = line_comment_prefix + self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks + self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline + + # runtime information + self.undefined = undefined + self.optimized = optimized + self.finalize = finalize + self.autoescape = autoescape + + # defaults + self.filters = DEFAULT_FILTERS.copy() + self.tests = DEFAULT_TESTS.copy() + self.globals = DEFAULT_NAMESPACE.copy() + + # set the loader provided + self.loader = loader + self.cache = create_cache(cache_size) + self.bytecode_cache = bytecode_cache + self.auto_reload = auto_reload + + # configurable policies + self.policies = DEFAULT_POLICIES.copy() + + # load extensions + self.extensions = load_extensions(self, extensions) + + self.enable_async = enable_async + self.is_async = self.enable_async and have_async_gen + if self.is_async: + # runs patch_all() to enable async support + from . import asyncsupport # noqa: F401 + + _environment_sanity_check(self) + + def add_extension(self, extension): + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + + def extend(self, **attributes): + """Add the items to the instance of the environment if they do not exist + yet. This is used by :ref:`extensions ` to register + callbacks and configuration values without breaking inheritance. + """ + for key, value in iteritems(attributes): + if not hasattr(self, key): + setattr(self, key, value) + + def overlay( + self, + block_start_string=missing, + block_end_string=missing, + variable_start_string=missing, + variable_end_string=missing, + comment_start_string=missing, + comment_end_string=missing, + line_statement_prefix=missing, + line_comment_prefix=missing, + trim_blocks=missing, + lstrip_blocks=missing, + extensions=missing, + optimized=missing, + undefined=missing, + finalize=missing, + autoescape=missing, + loader=missing, + cache_size=missing, + auto_reload=missing, + bytecode_cache=missing, + ): + """Create a new overlay environment that shares all the data with the + current environment except for cache and the overridden attributes. + Extensions cannot be removed for an overlayed environment. An overlayed + environment automatically gets all the extensions of the environment it + is linked to plus optional extra extensions. + + Creating overlays should happen after the initial environment was set + up completely. Not all attributes are truly linked, some are just + copied over so modifications on the original environment may not shine + through. + """ + args = dict(locals()) + del args["self"], args["cache_size"], args["extensions"] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in iteritems(args): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in iteritems(self.extensions): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + return _environment_sanity_check(rv) + + lexer = property(get_lexer, doc="The lexer for this environment.") + + def iter_extensions(self): + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) + + def getitem(self, obj, argument): + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (AttributeError, TypeError, LookupError): + if isinstance(argument, string_types): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj, attribute): + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a bytestring. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def call_filter( + self, name, value, args=None, kwargs=None, context=None, eval_ctx=None + ): + """Invokes a filter on a value the same way the compiler does it. + + Note that on Python 3 this might return a coroutine in case the + filter is running from an environment in async mode and the filter + supports async execution. It's your responsibility to await this + if needed. + + .. versionadded:: 2.7 + """ + func = self.filters.get(name) + if func is None: + fail_for_missing_callable("no filter named %r", name) + args = [value] + list(args or ()) + if getattr(func, "contextfilter", False) is True: + if context is None: + raise TemplateRuntimeError( + "Attempted to invoke context filter without context" + ) + args.insert(0, context) + elif getattr(func, "evalcontextfilter", False) is True: + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + args.insert(0, eval_ctx) + elif getattr(func, "environmentfilter", False) is True: + args.insert(0, self) + return func(*args, **(kwargs or {})) + + def call_test(self, name, value, args=None, kwargs=None): + """Invokes a test on a value the same way the compiler does it. + + .. versionadded:: 2.7 + """ + func = self.tests.get(name) + if func is None: + fail_for_missing_callable("no test named %r", name) + return func(value, *(args or ()), **(kwargs or {})) + + @internalcode + def parse(self, source, name=None, filename=None): + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def _parse(self, source, name, filename): + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, encode_filename(filename)).parse() + + def lex(self, source, name=None, filename=None): + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = text_type(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def preprocess(self, source, name=None, filename=None): + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce( + lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), + text_type(source), + ) + + def _tokenize(self, source, name, filename=None, state=None): + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + return stream + + def _generate(self, source, name, filename, defer_init=False): + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate( + source, + self, + name, + filename, + defer_init=defer_init, + optimized=self.optimized, + ) + + def _compile(self, source, filename): + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, "exec") + + @internalcode + def compile(self, source, name=None, filename=None, raw=False, defer_init=False): + """Compile a node or template source code. The `name` parameter is + the load name of the template after it was joined using + :meth:`join_path` if necessary, not the filename on the file system. + the `filename` parameter is the estimated filename of the template on + the file system. If the template came from a database or memory this + can be omitted. + + The return value of this method is a python code object. If the `raw` + parameter is `True` the return value will be a string with python + code equivalent to the bytecode returned otherwise. This method is + mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. + """ + source_hint = None + try: + if isinstance(source, string_types): + source_hint = source + source = self._parse(source, name, filename) + source = self._generate(source, name, filename, defer_init=defer_init) + if raw: + return source + if filename is None: + filename = "

UZVQ>{qJ_ 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̧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 GNeKX9BLVvW literal 0 HcmV?d00001 diff --git a/magma/squid_cnf/charms/squid/src/charm.py b/magma/squid_cnf/charms/squid/src/charm.py index 663410e5..e861c025 100755 --- a/magma/squid_cnf/charms/squid/src/charm.py +++ b/magma/squid_cnf/charms/squid/src/charm.py @@ -1,120 +1,114 @@ #! /usr/bin/env python3 -# -*- coding: utf-8 -*- -# vim:fenc=utf-8 -# Copyright © 2020 Dominik Fleischmann dominik.fleischmann@canonical.com -"""Operator Charm main library.""" -# Load modules from lib directory import logging +import subprocess -import setuppath # noqa:F401 +from ops.main import main from ops.charm import CharmBase from ops.framework import StoredState from ops.main import main -from ops.model import ActiveStatus, MaintenanceStatus -import subprocess +from ops.model import ActiveStatus, MaintenanceStatus, BlockedStatus + +from oci_image import OCIImageResource, OCIImageResourceError + +from jinja2 import Template + +SQUID_CONF = "/etc/squid/squid.conf" + +logger = logging.getLogger(__name__) class SquidK8SCharm(CharmBase): """Class reprisenting this Operator charm.""" - state = StoredState() + _stored = StoredState() def __init__(self, *args): """Initialize charm and configure states and events to observe.""" super().__init__(*args) - # -- standard hook observation - self.framework.observe(self.on.install, self.on_install) - self.framework.observe(self.on.start, self.on_start) - self.framework.observe(self.on.config_changed, self.on_config_changed) - self.framework.observe(self.on.deleteurl_action, self) - # -- initialize states -- - self.state.set_default(installed=False) - self.state.set_default(configured=False) - self.state.set_default(started=False) - - def make_pod_spec(self): - config = self.framework.model.config - ports = [{"name": "squid", "containerPort": config["port"], "protocol": "TCP"}] - - spec = { - "containers": [{ - "name": self.framework.model.app.name, - "image": config["image"], - "ports": ports, - }], - } - - return spec - - def _apply_spec(self, spec): - # Only apply the spec if this unit is a leader - if self.framework.model.unit.is_leader(): - self.framework.model.pod.set_spec(spec) - self.state.spec = spec - - def on_install(self, event): - """Handle install state.""" - self.unit.status = MaintenanceStatus("Installing charm software") - # Perform install tasks - self.unit.status = MaintenanceStatus("Install complete") - logging.info("Install of software complete") - self.state.installed = True - - def on_config_changed(self, event): - """Handle config changed.""" - - if not self.state.installed: - logging.warning("Config changed called before install complete, deferring event: {}.".format(event.handle)) - - return - - if self.state.started: - # Stop if necessary for reconfig - logging.info("Stopping for configuration, event handle: {}".format(event.handle)) - # Configure the software - logging.info("Configuring") - self.state.configured = True - - def on_start(self, event): - """Handle start state.""" - - if not self.state.configured: - logging.warning("Start called before configuration complete, deferring event: {}".format(event.handle)) + self._stored.set_default(pod_spec=None, allowedurls=set()) + + self.framework.observe(self.on.start, self.configure_pod) + self.framework.observe(self.on.config_changed, self.configure_pod) + self.framework.observe(self.on.addurl_action, self.on_addurl_action) + self.framework.observe(self.on.deleteurl_action, self.on_deleteurl_action) + + self.image = OCIImageResource(self, "image") + + def _update_allowed_urls(self, add: str = None, delete: str = None): + if add: + self._stored.allowedurls.add(add) + if delete and delete in self._stored.allowedurls: + self._stored.allowedurls.remove(delete) + + def _update_squid_config(self, add: str = None, delete: str = None): + self._update_allowed_urls(add=add, delete=delete) + squid_config_text = self._get_squid_config_file_text() + if squid_config_text: + with open(SQUID_CONF, "w") as f: + f.write(squid_config_text) + subprocess.Popen( + "sleep 1 && kill -HUP `cat /var/run/squid.pid`", shell=True + ) + + def on_addurl_action(self, event): + url = event.params["url"] + self._update_squid_config(add=url) + def on_deleteurl_action(self, event): + """Handle the deleteurl action.""" + url = event.params["url"] + self._update_squid_config(delete=url) + + def _get_squid_config_file_text(self): + squid_config_text = None + allowed_urls_text = "" + for url in self._stored.allowedurls: + allowed_urls_text += f"acl allowedurls dstdomain .{url}\n" + allowed_urls_text += "http_access allow allowedurls\n" + with open("template/squid.conf") as template: + squid_config_text = Template(template.read()).render( + allowed_urls=allowed_urls_text + ) + return squid_config_text + + def configure_pod(self, event): + if not self.unit.is_leader(): + self.unit.status = ActiveStatus("ready") return self.unit.status = MaintenanceStatus("Applying pod spec") - # Start software - new_pod_spec = self.make_pod_spec() - self._apply_spec(new_pod_spec) - self.unit.status = ActiveStatus("Unit is ready") - self.state.started = True - logging.info("Started") + # 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 - def on_deleteurl_action(self, event): - """Handle the deleteurl action.""" - url = event.params["url"] + pod_spec = self._make_pod_spec(image_info) - line_to_delete = "acl allowedurls dstdomain .{}".format(url) - line_deleted = False + if self._stored.pod_spec != pod_spec: + self.model.pod.set_spec(pod_spec) + self._stored.pod_spec = pod_spec + self.unit.status = ActiveStatus("ready") - with open("/etc/squid/squid.conf", "r") as f: - lines = f.readlines() - with open("/etc/squid/squid.conf", "w") as f: - for line in lines: - if line_to_delete not in line: - f.write(line) - else: - line_deleted = True + def _make_pod_spec(self, image_info): + config = self.config + ports = [{"name": "squid", "containerPort": config["port"], "protocol": "TCP"}] - if line_deleted: - event.set_results({"output": "URL deleted succesfully"}) - subprocess.Popen("sleep 1 && kill -HUP `cat /var/run/squid.pid`", shell=True) - else: - event.fail("No URL was deleted") + spec = { + "version": 3, + "containers": [ + { + "name": self.framework.model.app.name, + "imageDetails": image_info, + "ports": ports, + } + ], + } + return spec if __name__ == "__main__": - from ops.main import main main(SquidK8SCharm) diff --git a/magma/squid_cnf/charms/squid/template/squid.conf b/magma/squid_cnf/charms/squid/template/squid.conf new file mode 100644 index 00000000..9dc7e8b6 --- /dev/null +++ b/magma/squid_cnf/charms/squid/template/squid.conf @@ -0,0 +1,26 @@ +acl SSL_ports port 443 +acl Safe_ports port 80 # http +acl Safe_ports port 21 # ftp +acl Safe_ports port 443 # https +acl Safe_ports port 70 # gopher +acl Safe_ports port 210 # wais +acl Safe_ports port 1025-65535 # unregistered ports +acl Safe_ports port 280 # http-mgmt +acl Safe_ports port 488 # gss-http +acl Safe_ports port 591 # filemaker +acl Safe_ports port 777 # multiling http +acl CONNECT method CONNECT +http_access deny !Safe_ports +http_access deny CONNECT !SSL_ports +http_access allow localhost manager +http_access deny manager +http_access allow localhost +{{ allowed_urls }} +http_access deny all +http_port 3128 +coredump_dir /var/spool/squid +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 +refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880 +refresh_pattern . 0 20% 4320 diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/INSTALLER b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/LICENSE.rst b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/LICENSE.rst new file mode 100644 index 00000000..c37cae49 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/METADATA b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/METADATA new file mode 100644 index 00000000..55c0f826 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/METADATA @@ -0,0 +1,106 @@ +Metadata-Version: 2.1 +Name: Jinja2 +Version: 2.11.2 +Summary: A very fast and expressive template engine. +Home-page: https://palletsprojects.com/p/jinja/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Code, https://github.com/pallets/jinja +Project-URL: Issue tracker, https://github.com/pallets/jinja/issues +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* +Description-Content-Type: text/x-rst +Requires-Dist: MarkupSafe (>=0.23) +Provides-Extra: i18n +Requires-Dist: Babel (>=0.8) ; extra == 'i18n' + +Jinja +===== + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Jinja2 + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +In A Nutshell +------------- + +.. code-block:: jinja + + {% extends "base.html" %} + {% block title %}Members{% endblock %} + {% block content %} +