Merge ~hellsworth/+git/appstream-cloud:built-appstream-generator into ~ubuntu-desktop/+git/appstream-cloud:built-appstream-generator
- Git
- lp:~hellsworth/+git/appstream-cloud
- built-appstream-generator
- Merge into built-appstream-generator
Proposed by
Heather Ellsworth
Status: | Merged |
---|---|
Merged at revision: | 8b0905935171995645a5627f358e9ccf9dc71c5e |
Proposed branch: | ~hellsworth/+git/appstream-cloud:built-appstream-generator |
Merge into: | ~ubuntu-desktop/+git/appstream-cloud:built-appstream-generator |
Diff against target: |
321997 lines (+318431/-0) 419 files modified
charms/appstream-generator/LICENSE (+202/-0) charms/appstream-generator/actions.yaml (+18/-0) charms/appstream-generator/config.yaml (+16/-0) charms/appstream-generator/dispatch (+3/-0) charms/appstream-generator/hooks/install (+3/-0) charms/appstream-generator/hooks/start (+3/-0) charms/appstream-generator/hooks/upgrade-charm (+3/-0) charms/appstream-generator/manifest.yaml (+13/-0) charms/appstream-generator/metadata.yaml (+18/-0) charms/appstream-generator/src/charm.py (+455/-0) charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/LICENSE.rst (+28/-0) charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/METADATA (+113/-0) charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/RECORD (+58/-0) charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/WHEEL (+5/-0) charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/entry_points.txt (+3/-0) charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/LICENSE.rst (+28/-0) charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/METADATA (+100/-0) charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/RECORD (+14/-0) charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/WHEEL (+5/-0) charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/PyYAML-6.0.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/PyYAML-6.0.dist-info/LICENSE (+20/-0) charms/appstream-generator/venv/PyYAML-6.0.dist-info/METADATA (+46/-0) charms/appstream-generator/venv/PyYAML-6.0.dist-info/RECORD (+43/-0) charms/appstream-generator/venv/PyYAML-6.0.dist-info/WHEEL (+8/-0) charms/appstream-generator/venv/PyYAML-6.0.dist-info/top_level.txt (+2/-0) charms/appstream-generator/venv/Tempita-0.5.2.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/Tempita-0.5.2.dist-info/METADATA (+30/-0) charms/appstream-generator/venv/Tempita-0.5.2.dist-info/RECORD (+14/-0) charms/appstream-generator/venv/Tempita-0.5.2.dist-info/WHEEL (+5/-0) charms/appstream-generator/venv/Tempita-0.5.2.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/Tempita-0.5.2.dist-info/zip-safe (+1/-0) charms/appstream-generator/venv/_yaml/__init__.py (+33/-0) charms/appstream-generator/venv/bin/charmsupport (+31/-0) charms/appstream-generator/venv/bin/chlp (+8/-0) charms/appstream-generator/venv/bin/netaddr (+8/-0) charms/appstream-generator/venv/bin/pbr (+8/-0) charms/appstream-generator/venv/bin/salt-call (+11/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/AUTHORS (+222/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/LICENSE (+202/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/METADATA (+82/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/RECORD (+338/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/WHEEL (+5/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/pbr.json (+1/-0) charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/charmhelpers/__init__.py (+99/-0) charms/appstream-generator/venv/charmhelpers/cli/README.rst (+57/-0) charms/appstream-generator/venv/charmhelpers/cli/__init__.py (+196/-0) charms/appstream-generator/venv/charmhelpers/cli/benchmark.py (+34/-0) charms/appstream-generator/venv/charmhelpers/cli/commands.py (+30/-0) charms/appstream-generator/venv/charmhelpers/cli/hookenv.py (+21/-0) charms/appstream-generator/venv/charmhelpers/cli/host.py (+29/-0) charms/appstream-generator/venv/charmhelpers/cli/unitdata.py (+46/-0) charms/appstream-generator/venv/charmhelpers/context.py (+205/-0) charms/appstream-generator/venv/charmhelpers/contrib/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/ansible/__init__.py (+306/-0) charms/appstream-generator/venv/charmhelpers/contrib/benchmark/__init__.py (+124/-0) charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/IMPORT (+4/-0) charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/__init__.py (+203/-0) charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/IMPORT (+14/-0) charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/nrpe.py (+522/-0) charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/volumes.py (+173/-0) charms/appstream-generator/venv/charmhelpers/contrib/database/__init__.py (+11/-0) charms/appstream-generator/venv/charmhelpers/contrib/database/mysql.py (+840/-0) charms/appstream-generator/venv/charmhelpers/contrib/hahelpers/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/hahelpers/apache.py (+90/-0) charms/appstream-generator/venv/charmhelpers/contrib/hahelpers/cluster.py (+451/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/README.hardening.md (+38/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/apache/__init__.py (+17/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/apache/checks/__init__.py (+29/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/apache/checks/config.py (+104/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/apache/templates/99-hardening.conf (+32/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/apache/templates/alias.conf (+31/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/audits/__init__.py (+54/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/audits/apache.py (+105/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/audits/apt.py (+104/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/audits/file.py (+550/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/apache.yaml (+16/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/apache.yaml.schema (+12/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/mysql.yaml (+38/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/mysql.yaml.schema (+15/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/os.yaml (+68/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/os.yaml.schema (+43/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/ssh.yaml (+49/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/defaults/ssh.yaml.schema (+42/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/harden.py (+96/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/__init__.py (+17/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/__init__.py (+48/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/apt.py (+37/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/limits.py (+53/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/login.py (+65/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/minimize_access.py (+50/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/pam.py (+132/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/profile.py (+49/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/securetty.py (+37/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/suid_sgid.py (+129/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/checks/sysctl.py (+209/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/10.hardcore.conf (+8/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/99-hardening.sh (+5/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/99-juju-hardening.conf (+7/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/login.defs (+349/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/modules (+117/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/passwdqc.conf (+11/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/pinerolo_profile.sh (+8/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/securetty (+11/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/host/templates/tally2 (+14/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/mysql/__init__.py (+17/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/mysql/checks/__init__.py (+29/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/mysql/checks/config.py (+87/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/mysql/templates/hardening.cnf (+12/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/ssh/__init__.py (+17/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/ssh/checks/__init__.py (+29/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/ssh/checks/config.py (+435/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/ssh/templates/ssh_config (+70/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/ssh/templates/sshd_config (+159/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/templating.py (+73/-0) charms/appstream-generator/venv/charmhelpers/contrib/hardening/utils.py (+155/-0) charms/appstream-generator/venv/charmhelpers/contrib/mellanox/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/mellanox/infiniband.py (+153/-0) charms/appstream-generator/venv/charmhelpers/contrib/network/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/network/ip.py (+603/-0) charms/appstream-generator/venv/charmhelpers/contrib/network/ovs/__init__.py (+693/-0) charms/appstream-generator/venv/charmhelpers/contrib/network/ovs/ovn.py (+233/-0) charms/appstream-generator/venv/charmhelpers/contrib/network/ovs/ovsdb.py (+246/-0) charms/appstream-generator/venv/charmhelpers/contrib/network/ovs/utils.py (+26/-0) charms/appstream-generator/venv/charmhelpers/contrib/network/ufw.py (+386/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/alternatives.py (+44/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/audits/__init__.py (+212/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/audits/openstack_security_guide.py (+270/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/cert_utils.py (+443/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/context.py (+3363/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/deferred_events.py (+416/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/exceptions.py (+26/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/files/__init__.py (+16/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/files/check_haproxy.sh (+34/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/files/check_haproxy_queue_depth.sh (+30/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/files/policy_rc_d_script.py (+196/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/ha/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/ha/utils.py (+348/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/ip.py (+235/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/keystone.py (+178/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/neutron.py (+359/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/policy_rcd.py (+173/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/policyd.py (+801/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/ssh_migrations.py (+412/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/__init__.py (+16/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/ceph.conf (+28/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/git.upstart (+17/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/haproxy.cfg (+89/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/logrotate (+9/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/memcached.conf (+53/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/openstack_https_frontend (+35/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf (+35/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-ceph-bluestore-compression (+28/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-keystone-authtoken (+12/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-keystone-authtoken-legacy (+10/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-keystone-authtoken-mitaka (+22/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-keystone-authtoken-v3only (+9/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-oslo-cache (+6/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-oslo-messaging-rabbit (+10/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-oslo-messaging-rabbit-ocata (+10/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-oslo-middleware (+5/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-oslo-notifications (+15/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-placement (+20/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-rabbitmq-oslo (+22/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/section-zeromq (+14/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/vendor_data.json (+1/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf (+91/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templates/wsgi-openstack-metadata.conf (+91/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/templating.py (+379/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/utils.py (+2643/-0) charms/appstream-generator/venv/charmhelpers/contrib/openstack/vaultlocker.py (+179/-0) charms/appstream-generator/venv/charmhelpers/contrib/peerstorage/__init__.py (+267/-0) charms/appstream-generator/venv/charmhelpers/contrib/python.py (+21/-0) charms/appstream-generator/venv/charmhelpers/contrib/saltstack/__init__.py (+116/-0) charms/appstream-generator/venv/charmhelpers/contrib/ssl/__init__.py (+92/-0) charms/appstream-generator/venv/charmhelpers/contrib/ssl/service.py (+277/-0) charms/appstream-generator/venv/charmhelpers/contrib/storage/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/storage/linux/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/storage/linux/bcache.py (+74/-0) charms/appstream-generator/venv/charmhelpers/contrib/storage/linux/ceph.py (+2378/-0) charms/appstream-generator/venv/charmhelpers/contrib/storage/linux/loopback.py (+92/-0) charms/appstream-generator/venv/charmhelpers/contrib/storage/linux/lvm.py (+182/-0) charms/appstream-generator/venv/charmhelpers/contrib/storage/linux/utils.py (+128/-0) charms/appstream-generator/venv/charmhelpers/contrib/sysctl/__init__.py (+0/-0) charms/appstream-generator/venv/charmhelpers/contrib/sysctl/watermark_scale_factor.py (+104/-0) charms/appstream-generator/venv/charmhelpers/contrib/templating/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/contrib/templating/contexts.py (+137/-0) charms/appstream-generator/venv/charmhelpers/contrib/templating/jinja.py (+51/-0) charms/appstream-generator/venv/charmhelpers/contrib/templating/pyformat.py (+27/-0) charms/appstream-generator/venv/charmhelpers/contrib/unison/__init__.py (+316/-0) charms/appstream-generator/venv/charmhelpers/coordinator.py (+606/-0) charms/appstream-generator/venv/charmhelpers/core/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/core/decorators.py (+93/-0) charms/appstream-generator/venv/charmhelpers/core/files.py (+43/-0) charms/appstream-generator/venv/charmhelpers/core/fstab.py (+132/-0) charms/appstream-generator/venv/charmhelpers/core/hookenv.py (+1639/-0) charms/appstream-generator/venv/charmhelpers/core/host.py (+1279/-0) charms/appstream-generator/venv/charmhelpers/core/host_factory/__init__.py (+0/-0) charms/appstream-generator/venv/charmhelpers/core/host_factory/centos.py (+72/-0) charms/appstream-generator/venv/charmhelpers/core/host_factory/ubuntu.py (+121/-0) charms/appstream-generator/venv/charmhelpers/core/hugepage.py (+69/-0) charms/appstream-generator/venv/charmhelpers/core/kernel.py (+72/-0) charms/appstream-generator/venv/charmhelpers/core/kernel_factory/__init__.py (+0/-0) charms/appstream-generator/venv/charmhelpers/core/kernel_factory/centos.py (+17/-0) charms/appstream-generator/venv/charmhelpers/core/kernel_factory/ubuntu.py (+13/-0) charms/appstream-generator/venv/charmhelpers/core/services/__init__.py (+16/-0) charms/appstream-generator/venv/charmhelpers/core/services/base.py (+367/-0) charms/appstream-generator/venv/charmhelpers/core/services/helpers.py (+290/-0) charms/appstream-generator/venv/charmhelpers/core/strutils.py (+132/-0) charms/appstream-generator/venv/charmhelpers/core/sysctl.py (+75/-0) charms/appstream-generator/venv/charmhelpers/core/templating.py (+93/-0) charms/appstream-generator/venv/charmhelpers/core/unitdata.py (+525/-0) charms/appstream-generator/venv/charmhelpers/fetch/__init__.py (+212/-0) charms/appstream-generator/venv/charmhelpers/fetch/archiveurl.py (+165/-0) charms/appstream-generator/venv/charmhelpers/fetch/bzrurl.py (+76/-0) charms/appstream-generator/venv/charmhelpers/fetch/centos.py (+171/-0) charms/appstream-generator/venv/charmhelpers/fetch/giturl.py (+69/-0) charms/appstream-generator/venv/charmhelpers/fetch/python/__init__.py (+13/-0) charms/appstream-generator/venv/charmhelpers/fetch/python/debug.py (+54/-0) charms/appstream-generator/venv/charmhelpers/fetch/python/packages.py (+156/-0) charms/appstream-generator/venv/charmhelpers/fetch/python/rpdb.py (+56/-0) charms/appstream-generator/venv/charmhelpers/fetch/python/version.py (+32/-0) charms/appstream-generator/venv/charmhelpers/fetch/snap.py (+150/-0) charms/appstream-generator/venv/charmhelpers/fetch/ubuntu.py (+1011/-0) charms/appstream-generator/venv/charmhelpers/fetch/ubuntu_apt_pkg.py (+312/-0) charms/appstream-generator/venv/charmhelpers/osplatform.py (+49/-0) charms/appstream-generator/venv/charmhelpers/payload/__init__.py (+15/-0) charms/appstream-generator/venv/charmhelpers/payload/archive.py (+71/-0) charms/appstream-generator/venv/charmhelpers/payload/execd.py (+65/-0) charms/appstream-generator/venv/charmhelpers/version.py (+2/-0) charms/appstream-generator/venv/jinja2/__init__.py (+45/-0) charms/appstream-generator/venv/jinja2/_identifier.py (+6/-0) charms/appstream-generator/venv/jinja2/async_utils.py (+68/-0) charms/appstream-generator/venv/jinja2/bccache.py (+364/-0) charms/appstream-generator/venv/jinja2/compiler.py (+1957/-0) charms/appstream-generator/venv/jinja2/constants.py (+20/-0) charms/appstream-generator/venv/jinja2/debug.py (+279/-0) charms/appstream-generator/venv/jinja2/defaults.py (+48/-0) charms/appstream-generator/venv/jinja2/environment.py (+1674/-0) charms/appstream-generator/venv/jinja2/exceptions.py (+166/-0) charms/appstream-generator/venv/jinja2/ext.py (+879/-0) charms/appstream-generator/venv/jinja2/filters.py (+1824/-0) charms/appstream-generator/venv/jinja2/idtracking.py (+318/-0) charms/appstream-generator/venv/jinja2/lexer.py (+869/-0) charms/appstream-generator/venv/jinja2/loaders.py (+644/-0) charms/appstream-generator/venv/jinja2/meta.py (+111/-0) charms/appstream-generator/venv/jinja2/nativetypes.py (+118/-0) charms/appstream-generator/venv/jinja2/nodes.py (+1205/-0) charms/appstream-generator/venv/jinja2/optimizer.py (+47/-0) charms/appstream-generator/venv/jinja2/parser.py (+1040/-0) charms/appstream-generator/venv/jinja2/py.typed (+0/-0) charms/appstream-generator/venv/jinja2/runtime.py (+1104/-0) charms/appstream-generator/venv/jinja2/sandbox.py (+428/-0) charms/appstream-generator/venv/jinja2/tests.py (+255/-0) charms/appstream-generator/venv/jinja2/utils.py (+854/-0) charms/appstream-generator/venv/jinja2/visitor.py (+92/-0) charms/appstream-generator/venv/markupsafe/__init__.py (+288/-0) charms/appstream-generator/venv/markupsafe/_native.py (+75/-0) charms/appstream-generator/venv/markupsafe/_speedups.c (+339/-0) charms/appstream-generator/venv/markupsafe/_speedups.pyi (+9/-0) charms/appstream-generator/venv/markupsafe/py.typed (+0/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/AUTHORS (+5/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/LICENSE (+36/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/METADATA (+118/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/RECORD (+57/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/WHEEL (+6/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/entry_points.txt (+3/-0) charms/appstream-generator/venv/netaddr-0.8.0.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/netaddr/__init__.py (+48/-0) charms/appstream-generator/venv/netaddr/cli.py (+42/-0) charms/appstream-generator/venv/netaddr/compat.py (+93/-0) charms/appstream-generator/venv/netaddr/contrib/__init__.py (+12/-0) charms/appstream-generator/venv/netaddr/contrib/subnet_splitter.py (+46/-0) charms/appstream-generator/venv/netaddr/core.py (+206/-0) charms/appstream-generator/venv/netaddr/eui/__init__.py (+749/-0) charms/appstream-generator/venv/netaddr/eui/iab.idx (+4575/-0) charms/appstream-generator/venv/netaddr/eui/iab.txt (+27381/-0) charms/appstream-generator/venv/netaddr/eui/ieee.py (+293/-0) charms/appstream-generator/venv/netaddr/eui/oui.idx (+28112/-0) charms/appstream-generator/venv/netaddr/eui/oui.txt (+168378/-0) charms/appstream-generator/venv/netaddr/fbsocket.py (+246/-0) charms/appstream-generator/venv/netaddr/ip/__init__.py (+1972/-0) charms/appstream-generator/venv/netaddr/ip/glob.py (+312/-0) charms/appstream-generator/venv/netaddr/ip/iana.py (+448/-0) charms/appstream-generator/venv/netaddr/ip/ipv4-address-space.xml (+2644/-0) charms/appstream-generator/venv/netaddr/ip/ipv6-address-space.xml (+198/-0) charms/appstream-generator/venv/netaddr/ip/ipv6-unicast-address-assignments.xml (+435/-0) charms/appstream-generator/venv/netaddr/ip/multicast-addresses.xml (+4441/-0) charms/appstream-generator/venv/netaddr/ip/nmap.py (+117/-0) charms/appstream-generator/venv/netaddr/ip/rfc1924.py (+61/-0) charms/appstream-generator/venv/netaddr/ip/sets.py (+748/-0) charms/appstream-generator/venv/netaddr/strategy/__init__.py (+273/-0) charms/appstream-generator/venv/netaddr/strategy/eui48.py (+296/-0) charms/appstream-generator/venv/netaddr/strategy/eui64.py (+273/-0) charms/appstream-generator/venv/netaddr/strategy/ipv4.py (+279/-0) charms/appstream-generator/venv/netaddr/strategy/ipv6.py (+259/-0) charms/appstream-generator/venv/ops-1.2.0.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/ops-1.2.0.dist-info/METADATA (+263/-0) charms/appstream-generator/venv/ops-1.2.0.dist-info/RECORD (+33/-0) charms/appstream-generator/venv/ops-1.2.0.dist-info/WHEEL (+5/-0) charms/appstream-generator/venv/ops-1.2.0.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/ops/__init__.py (+44/-0) charms/appstream-generator/venv/ops/_private/__init__.py (+0/-0) charms/appstream-generator/venv/ops/_private/yaml.py (+32/-0) charms/appstream-generator/venv/ops/charm.py (+893/-0) charms/appstream-generator/venv/ops/framework.py (+1199/-0) charms/appstream-generator/venv/ops/jujuversion.py (+114/-0) charms/appstream-generator/venv/ops/lib/__init__.py (+264/-0) charms/appstream-generator/venv/ops/log.py (+58/-0) charms/appstream-generator/venv/ops/main.py (+410/-0) charms/appstream-generator/venv/ops/model.py (+1579/-0) charms/appstream-generator/venv/ops/pebble.py (+1112/-0) charms/appstream-generator/venv/ops/storage.py (+374/-0) charms/appstream-generator/venv/ops/testing.py (+1111/-0) charms/appstream-generator/venv/ops/version.py (+3/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/AUTHORS (+153/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/LICENSE (+176/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/METADATA (+75/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/RECORD (+110/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/WHEEL (+6/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/entry_points.txt (+9/-0) charms/appstream-generator/venv/pbr-5.6.0.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/pbr/__init__.py (+0/-0) charms/appstream-generator/venv/pbr/builddoc.py (+292/-0) charms/appstream-generator/venv/pbr/cmd/__init__.py (+0/-0) charms/appstream-generator/venv/pbr/cmd/main.py (+119/-0) charms/appstream-generator/venv/pbr/core.py (+145/-0) charms/appstream-generator/venv/pbr/extra_files.py (+35/-0) charms/appstream-generator/venv/pbr/find_package.py (+29/-0) charms/appstream-generator/venv/pbr/git.py (+338/-0) charms/appstream-generator/venv/pbr/hooks/__init__.py (+28/-0) charms/appstream-generator/venv/pbr/hooks/backwards.py (+33/-0) charms/appstream-generator/venv/pbr/hooks/base.py (+34/-0) charms/appstream-generator/venv/pbr/hooks/commands.py (+66/-0) charms/appstream-generator/venv/pbr/hooks/files.py (+126/-0) charms/appstream-generator/venv/pbr/hooks/metadata.py (+32/-0) charms/appstream-generator/venv/pbr/options.py (+53/-0) charms/appstream-generator/venv/pbr/packaging.py (+887/-0) charms/appstream-generator/venv/pbr/pbr_json.py (+34/-0) charms/appstream-generator/venv/pbr/sphinxext.py (+99/-0) charms/appstream-generator/venv/pbr/testr_command.py (+167/-0) charms/appstream-generator/venv/pbr/tests/__init__.py (+26/-0) charms/appstream-generator/venv/pbr/tests/base.py (+226/-0) charms/appstream-generator/venv/pbr/tests/test_commands.py (+84/-0) charms/appstream-generator/venv/pbr/tests/test_core.py (+158/-0) charms/appstream-generator/venv/pbr/tests/test_files.py (+148/-0) charms/appstream-generator/venv/pbr/tests/test_hooks.py (+75/-0) charms/appstream-generator/venv/pbr/tests/test_integration.py (+286/-0) charms/appstream-generator/venv/pbr/tests/test_packaging.py (+1113/-0) charms/appstream-generator/venv/pbr/tests/test_pbr_json.py (+30/-0) charms/appstream-generator/venv/pbr/tests/test_setup.py (+447/-0) charms/appstream-generator/venv/pbr/tests/test_util.py (+320/-0) charms/appstream-generator/venv/pbr/tests/test_version.py (+311/-0) charms/appstream-generator/venv/pbr/tests/test_wsgi.py (+163/-0) charms/appstream-generator/venv/pbr/tests/testpackage/CHANGES.txt (+86/-0) charms/appstream-generator/venv/pbr/tests/testpackage/LICENSE.txt (+29/-0) charms/appstream-generator/venv/pbr/tests/testpackage/MANIFEST.in (+2/-0) charms/appstream-generator/venv/pbr/tests/testpackage/README.txt (+148/-0) charms/appstream-generator/venv/pbr/tests/testpackage/data_files/a.txt (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/data_files/b.txt (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/data_files/c.rst (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/doc/source/conf.py (+59/-0) charms/appstream-generator/venv/pbr/tests/testpackage/doc/source/index.rst (+23/-0) charms/appstream-generator/venv/pbr/tests/testpackage/doc/source/installation.rst (+12/-0) charms/appstream-generator/venv/pbr/tests/testpackage/doc/source/usage.rst (+7/-0) charms/appstream-generator/venv/pbr/tests/testpackage/extra-file.txt (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/git-extra-file.txt (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/pbr_testpackage/__init__.py (+3/-0) charms/appstream-generator/venv/pbr/tests/testpackage/pbr_testpackage/_setup_hooks.py (+65/-0) charms/appstream-generator/venv/pbr/tests/testpackage/pbr_testpackage/cmd.py (+26/-0) charms/appstream-generator/venv/pbr/tests/testpackage/pbr_testpackage/extra.py (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/pbr_testpackage/package_data/1.txt (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/pbr_testpackage/package_data/2.txt (+0/-0) charms/appstream-generator/venv/pbr/tests/testpackage/pbr_testpackage/wsgi.py (+40/-0) charms/appstream-generator/venv/pbr/tests/testpackage/setup.cfg (+58/-0) charms/appstream-generator/venv/pbr/tests/testpackage/setup.py (+21/-0) charms/appstream-generator/venv/pbr/tests/testpackage/src/testext.c (+29/-0) charms/appstream-generator/venv/pbr/tests/testpackage/test-requirements.txt (+2/-0) charms/appstream-generator/venv/pbr/tests/util.py (+78/-0) charms/appstream-generator/venv/pbr/util.py (+621/-0) charms/appstream-generator/venv/pbr/version.py (+483/-0) charms/appstream-generator/venv/six-1.16.0.dist-info/INSTALLER (+1/-0) charms/appstream-generator/venv/six-1.16.0.dist-info/LICENSE (+18/-0) charms/appstream-generator/venv/six-1.16.0.dist-info/METADATA (+49/-0) charms/appstream-generator/venv/six-1.16.0.dist-info/RECORD (+8/-0) charms/appstream-generator/venv/six-1.16.0.dist-info/WHEEL (+6/-0) charms/appstream-generator/venv/six-1.16.0.dist-info/top_level.txt (+1/-0) charms/appstream-generator/venv/six.py (+998/-0) charms/appstream-generator/venv/tempita/__init__.py (+1187/-0) charms/appstream-generator/venv/tempita/__main__.py (+3/-0) charms/appstream-generator/venv/tempita/_looper.py (+164/-0) charms/appstream-generator/venv/tempita/compat3.py (+45/-0) charms/appstream-generator/venv/yaml/__init__.py (+390/-0) charms/appstream-generator/venv/yaml/composer.py (+139/-0) charms/appstream-generator/venv/yaml/constructor.py (+748/-0) charms/appstream-generator/venv/yaml/cyaml.py (+101/-0) charms/appstream-generator/venv/yaml/dumper.py (+62/-0) charms/appstream-generator/venv/yaml/emitter.py (+1137/-0) charms/appstream-generator/venv/yaml/error.py (+75/-0) charms/appstream-generator/venv/yaml/events.py (+86/-0) charms/appstream-generator/venv/yaml/loader.py (+63/-0) charms/appstream-generator/venv/yaml/nodes.py (+49/-0) charms/appstream-generator/venv/yaml/parser.py (+589/-0) charms/appstream-generator/venv/yaml/reader.py (+185/-0) charms/appstream-generator/venv/yaml/representer.py (+389/-0) charms/appstream-generator/venv/yaml/resolver.py (+227/-0) charms/appstream-generator/venv/yaml/scanner.py (+1435/-0) charms/appstream-generator/venv/yaml/serializer.py (+111/-0) charms/appstream-generator/venv/yaml/tokens.py (+104/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Desktop | Pending | ||
Review via email: mp+410902@code.launchpad.net |
Commit message
New build
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/charms/appstream-generator/LICENSE b/charms/appstream-generator/LICENSE |
2 | new file mode 100644 |
3 | index 0000000..d645695 |
4 | --- /dev/null |
5 | +++ b/charms/appstream-generator/LICENSE |
6 | @@ -0,0 +1,202 @@ |
7 | + |
8 | + Apache License |
9 | + Version 2.0, January 2004 |
10 | + http://www.apache.org/licenses/ |
11 | + |
12 | + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
13 | + |
14 | + 1. Definitions. |
15 | + |
16 | + "License" shall mean the terms and conditions for use, reproduction, |
17 | + and distribution as defined by Sections 1 through 9 of this document. |
18 | + |
19 | + "Licensor" shall mean the copyright owner or entity authorized by |
20 | + the copyright owner that is granting the License. |
21 | + |
22 | + "Legal Entity" shall mean the union of the acting entity and all |
23 | + other entities that control, are controlled by, or are under common |
24 | + control with that entity. For the purposes of this definition, |
25 | + "control" means (i) the power, direct or indirect, to cause the |
26 | + direction or management of such entity, whether by contract or |
27 | + otherwise, or (ii) ownership of fifty percent (50%) or more of the |
28 | + outstanding shares, or (iii) beneficial ownership of such entity. |
29 | + |
30 | + "You" (or "Your") shall mean an individual or Legal Entity |
31 | + exercising permissions granted by this License. |
32 | + |
33 | + "Source" form shall mean the preferred form for making modifications, |
34 | + including but not limited to software source code, documentation |
35 | + source, and configuration files. |
36 | + |
37 | + "Object" form shall mean any form resulting from mechanical |
38 | + transformation or translation of a Source form, including but |
39 | + not limited to compiled object code, generated documentation, |
40 | + and conversions to other media types. |
41 | + |
42 | + "Work" shall mean the work of authorship, whether in Source or |
43 | + Object form, made available under the License, as indicated by a |
44 | + copyright notice that is included in or attached to the work |
45 | + (an example is provided in the Appendix below). |
46 | + |
47 | + "Derivative Works" shall mean any work, whether in Source or Object |
48 | + form, that is based on (or derived from) the Work and for which the |
49 | + editorial revisions, annotations, elaborations, or other modifications |
50 | + represent, as a whole, an original work of authorship. For the purposes |
51 | + of this License, Derivative Works shall not include works that remain |
52 | + separable from, or merely link (or bind by name) to the interfaces of, |
53 | + the Work and Derivative Works thereof. |
54 | + |
55 | + "Contribution" shall mean any work of authorship, including |
56 | + the original version of the Work and any modifications or additions |
57 | + to that Work or Derivative Works thereof, that is intentionally |
58 | + submitted to Licensor for inclusion in the Work by the copyright owner |
59 | + or by an individual or Legal Entity authorized to submit on behalf of |
60 | + the copyright owner. For the purposes of this definition, "submitted" |
61 | + means any form of electronic, verbal, or written communication sent |
62 | + to the Licensor or its representatives, including but not limited to |
63 | + communication on electronic mailing lists, source code control systems, |
64 | + and issue tracking systems that are managed by, or on behalf of, the |
65 | + Licensor for the purpose of discussing and improving the Work, but |
66 | + excluding communication that is conspicuously marked or otherwise |
67 | + designated in writing by the copyright owner as "Not a Contribution." |
68 | + |
69 | + "Contributor" shall mean Licensor and any individual or Legal Entity |
70 | + on behalf of whom a Contribution has been received by Licensor and |
71 | + subsequently incorporated within the Work. |
72 | + |
73 | + 2. Grant of Copyright License. Subject to the terms and conditions of |
74 | + this License, each Contributor hereby grants to You a perpetual, |
75 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
76 | + copyright license to reproduce, prepare Derivative Works of, |
77 | + publicly display, publicly perform, sublicense, and distribute the |
78 | + Work and such Derivative Works in Source or Object form. |
79 | + |
80 | + 3. Grant of Patent License. Subject to the terms and conditions of |
81 | + this License, each Contributor hereby grants to You a perpetual, |
82 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
83 | + (except as stated in this section) patent license to make, have made, |
84 | + use, offer to sell, sell, import, and otherwise transfer the Work, |
85 | + where such license applies only to those patent claims licensable |
86 | + by such Contributor that are necessarily infringed by their |
87 | + Contribution(s) alone or by combination of their Contribution(s) |
88 | + with the Work to which such Contribution(s) was submitted. If You |
89 | + institute patent litigation against any entity (including a |
90 | + cross-claim or counterclaim in a lawsuit) alleging that the Work |
91 | + or a Contribution incorporated within the Work constitutes direct |
92 | + or contributory patent infringement, then any patent licenses |
93 | + granted to You under this License for that Work shall terminate |
94 | + as of the date such litigation is filed. |
95 | + |
96 | + 4. Redistribution. You may reproduce and distribute copies of the |
97 | + Work or Derivative Works thereof in any medium, with or without |
98 | + modifications, and in Source or Object form, provided that You |
99 | + meet the following conditions: |
100 | + |
101 | + (a) You must give any other recipients of the Work or |
102 | + Derivative Works a copy of this License; and |
103 | + |
104 | + (b) You must cause any modified files to carry prominent notices |
105 | + stating that You changed the files; and |
106 | + |
107 | + (c) You must retain, in the Source form of any Derivative Works |
108 | + that You distribute, all copyright, patent, trademark, and |
109 | + attribution notices from the Source form of the Work, |
110 | + excluding those notices that do not pertain to any part of |
111 | + the Derivative Works; and |
112 | + |
113 | + (d) If the Work includes a "NOTICE" text file as part of its |
114 | + distribution, then any Derivative Works that You distribute must |
115 | + include a readable copy of the attribution notices contained |
116 | + within such NOTICE file, excluding those notices that do not |
117 | + pertain to any part of the Derivative Works, in at least one |
118 | + of the following places: within a NOTICE text file distributed |
119 | + as part of the Derivative Works; within the Source form or |
120 | + documentation, if provided along with the Derivative Works; or, |
121 | + within a display generated by the Derivative Works, if and |
122 | + wherever such third-party notices normally appear. The contents |
123 | + of the NOTICE file are for informational purposes only and |
124 | + do not modify the License. You may add Your own attribution |
125 | + notices within Derivative Works that You distribute, alongside |
126 | + or as an addendum to the NOTICE text from the Work, provided |
127 | + that such additional attribution notices cannot be construed |
128 | + as modifying the License. |
129 | + |
130 | + You may add Your own copyright statement to Your modifications and |
131 | + may provide additional or different license terms and conditions |
132 | + for use, reproduction, or distribution of Your modifications, or |
133 | + for any such Derivative Works as a whole, provided Your use, |
134 | + reproduction, and distribution of the Work otherwise complies with |
135 | + the conditions stated in this License. |
136 | + |
137 | + 5. Submission of Contributions. Unless You explicitly state otherwise, |
138 | + any Contribution intentionally submitted for inclusion in the Work |
139 | + by You to the Licensor shall be under the terms and conditions of |
140 | + this License, without any additional terms or conditions. |
141 | + Notwithstanding the above, nothing herein shall supersede or modify |
142 | + the terms of any separate license agreement you may have executed |
143 | + with Licensor regarding such Contributions. |
144 | + |
145 | + 6. Trademarks. This License does not grant permission to use the trade |
146 | + names, trademarks, service marks, or product names of the Licensor, |
147 | + except as required for reasonable and customary use in describing the |
148 | + origin of the Work and reproducing the content of the NOTICE file. |
149 | + |
150 | + 7. Disclaimer of Warranty. Unless required by applicable law or |
151 | + agreed to in writing, Licensor provides the Work (and each |
152 | + Contributor provides its Contributions) on an "AS IS" BASIS, |
153 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
154 | + implied, including, without limitation, any warranties or conditions |
155 | + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
156 | + PARTICULAR PURPOSE. You are solely responsible for determining the |
157 | + appropriateness of using or redistributing the Work and assume any |
158 | + risks associated with Your exercise of permissions under this License. |
159 | + |
160 | + 8. Limitation of Liability. In no event and under no legal theory, |
161 | + whether in tort (including negligence), contract, or otherwise, |
162 | + unless required by applicable law (such as deliberate and grossly |
163 | + negligent acts) or agreed to in writing, shall any Contributor be |
164 | + liable to You for damages, including any direct, indirect, special, |
165 | + incidental, or consequential damages of any character arising as a |
166 | + result of this License or out of the use or inability to use the |
167 | + Work (including but not limited to damages for loss of goodwill, |
168 | + work stoppage, computer failure or malfunction, or any and all |
169 | + other commercial damages or losses), even if such Contributor |
170 | + has been advised of the possibility of such damages. |
171 | + |
172 | + 9. Accepting Warranty or Additional Liability. While redistributing |
173 | + the Work or Derivative Works thereof, You may choose to offer, |
174 | + and charge a fee for, acceptance of support, warranty, indemnity, |
175 | + or other liability obligations and/or rights consistent with this |
176 | + License. However, in accepting such obligations, You may act only |
177 | + on Your own behalf and on Your sole responsibility, not on behalf |
178 | + of any other Contributor, and only if You agree to indemnify, |
179 | + defend, and hold each Contributor harmless for any liability |
180 | + incurred by, or claims asserted against, such Contributor by reason |
181 | + of your accepting any such warranty or additional liability. |
182 | + |
183 | + END OF TERMS AND CONDITIONS |
184 | + |
185 | + APPENDIX: How to apply the Apache License to your work. |
186 | + |
187 | + To apply the Apache License to your work, attach the following |
188 | + boilerplate notice, with the fields enclosed by brackets "[]" |
189 | + replaced with your own identifying information. (Don't include |
190 | + the brackets!) The text should be enclosed in the appropriate |
191 | + comment syntax for the file format. We also recommend that a |
192 | + file or class name and description of purpose be included on the |
193 | + same "printed page" as the copyright notice for easier |
194 | + identification within third-party archives. |
195 | + |
196 | + Copyright [yyyy] [name of copyright owner] |
197 | + |
198 | + Licensed under the Apache License, Version 2.0 (the "License"); |
199 | + you may not use this file except in compliance with the License. |
200 | + You may obtain a copy of the License at |
201 | + |
202 | + http://www.apache.org/licenses/LICENSE-2.0 |
203 | + |
204 | + Unless required by applicable law or agreed to in writing, software |
205 | + distributed under the License is distributed on an "AS IS" BASIS, |
206 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
207 | + See the License for the specific language governing permissions and |
208 | + limitations under the License. |
209 | diff --git a/charms/appstream-generator/actions.yaml b/charms/appstream-generator/actions.yaml |
210 | new file mode 100644 |
211 | index 0000000..03a55e4 |
212 | --- /dev/null |
213 | +++ b/charms/appstream-generator/actions.yaml |
214 | @@ -0,0 +1,18 @@ |
215 | +clean: |
216 | + description: Clean up so that the next run forces a full refresh |
217 | +run-now: |
218 | + description: Run an update immediately |
219 | +forget: |
220 | + description: Forget packages from all releases, causing them to be reprocessed the next time |
221 | + params: |
222 | + packages: |
223 | + type: array |
224 | + items: { type: string } |
225 | + required: [packages] |
226 | +forget-tag: |
227 | + description: Forget all packages with a given tag, causing them to be reprocessed the next time |
228 | + params: |
229 | + tag: |
230 | + type: string |
231 | + description: The tag to forget |
232 | + required: [tag] |
233 | diff --git a/charms/appstream-generator/config.yaml b/charms/appstream-generator/config.yaml |
234 | new file mode 100644 |
235 | index 0000000..3d30680 |
236 | --- /dev/null |
237 | +++ b/charms/appstream-generator/config.yaml |
238 | @@ -0,0 +1,16 @@ |
239 | +options: |
240 | + hostname: |
241 | + description: The hostname the service will be presented on |
242 | + type: string |
243 | + config: |
244 | + description: The configuration of the asgen (releases, etc - see config.json) |
245 | + type: string |
246 | + mirror: |
247 | + default: http://archive.ubuntu.com/ubuntu/ |
248 | + default_snap_channel: |
249 | + description: When installing snaps, default to this channel |
250 | + type: string |
251 | + default: stable |
252 | + http_proxy: |
253 | + https_proxy: |
254 | + no_proxy: |
255 | diff --git a/charms/appstream-generator/dispatch b/charms/appstream-generator/dispatch |
256 | new file mode 100755 |
257 | index 0000000..fe31c05 |
258 | --- /dev/null |
259 | +++ b/charms/appstream-generator/dispatch |
260 | @@ -0,0 +1,3 @@ |
261 | +#!/bin/sh |
262 | + |
263 | +JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py |
264 | diff --git a/charms/appstream-generator/hooks/install b/charms/appstream-generator/hooks/install |
265 | new file mode 100755 |
266 | index 0000000..fe31c05 |
267 | --- /dev/null |
268 | +++ b/charms/appstream-generator/hooks/install |
269 | @@ -0,0 +1,3 @@ |
270 | +#!/bin/sh |
271 | + |
272 | +JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py |
273 | diff --git a/charms/appstream-generator/hooks/start b/charms/appstream-generator/hooks/start |
274 | new file mode 100755 |
275 | index 0000000..fe31c05 |
276 | --- /dev/null |
277 | +++ b/charms/appstream-generator/hooks/start |
278 | @@ -0,0 +1,3 @@ |
279 | +#!/bin/sh |
280 | + |
281 | +JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py |
282 | diff --git a/charms/appstream-generator/hooks/upgrade-charm b/charms/appstream-generator/hooks/upgrade-charm |
283 | new file mode 100755 |
284 | index 0000000..fe31c05 |
285 | --- /dev/null |
286 | +++ b/charms/appstream-generator/hooks/upgrade-charm |
287 | @@ -0,0 +1,3 @@ |
288 | +#!/bin/sh |
289 | + |
290 | +JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py |
291 | diff --git a/charms/appstream-generator/manifest.yaml b/charms/appstream-generator/manifest.yaml |
292 | new file mode 100644 |
293 | index 0000000..c8edade |
294 | --- /dev/null |
295 | +++ b/charms/appstream-generator/manifest.yaml |
296 | @@ -0,0 +1,13 @@ |
297 | +analysis: |
298 | + attributes: |
299 | + - name: language |
300 | + result: python |
301 | + - name: framework |
302 | + result: operator |
303 | +bases: |
304 | +- architectures: |
305 | + - amd64 |
306 | + channel: '20.04' |
307 | + name: ubuntu |
308 | +charmcraft-started-at: '2021-10-27T19:57:21.230918Z' |
309 | +charmcraft-version: 1.2.1 |
310 | diff --git a/charms/appstream-generator/metadata.yaml b/charms/appstream-generator/metadata.yaml |
311 | new file mode 100644 |
312 | index 0000000..099feed |
313 | --- /dev/null |
314 | +++ b/charms/appstream-generator/metadata.yaml |
315 | @@ -0,0 +1,18 @@ |
316 | +name: appstream-generator |
317 | +description: | |
318 | + Generate Appstream metadata from a distribution's software archive |
319 | +summary: | |
320 | + Generate Appstream metadata from a distribution's software archive |
321 | +series: [focal] |
322 | +storage: |
323 | + appstream: |
324 | + type: filesystem |
325 | + description: appstream-generator's output & working data |
326 | + shared: false |
327 | + read-only: false |
328 | + minimum-size: 200G |
329 | + location: /home/ubuntu/appstream |
330 | +provides: |
331 | + rsync: |
332 | + interface: appstream-rsync |
333 | + optional: true |
334 | diff --git a/charms/appstream-generator/src/charm.py b/charms/appstream-generator/src/charm.py |
335 | new file mode 100755 |
336 | index 0000000..b415f50 |
337 | --- /dev/null |
338 | +++ b/charms/appstream-generator/src/charm.py |
339 | @@ -0,0 +1,455 @@ |
340 | +#!/usr/bin/env python3 |
341 | +# Copyright 2021 Canonical Ltd |
342 | + |
343 | +# This program is free software: you can redistribute it and/or modify it under |
344 | +# the terms of the GNU General Public License as published by the Free Software |
345 | +# Foundation, either version 3 of the License, or (at your option) any later |
346 | +# version. |
347 | +# |
348 | +# This program is distributed in the hope that it will be useful, but WITHOUT |
349 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
350 | +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
351 | +# |
352 | +# You should have received a copy of the GNU General Public License along with |
353 | +# this program. If not, see <http://www.gnu.org/licenses/>. |
354 | + |
355 | +import json |
356 | +import logging |
357 | +import os |
358 | +import shutil |
359 | +import subprocess |
360 | +from pathlib import Path |
361 | +from textwrap import dedent |
362 | + |
363 | +from charmhelpers.core.hookenv import open_port |
364 | +from ops.charm import CharmBase |
365 | +from ops.framework import StoredState |
366 | +from ops.main import main |
367 | +from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus |
368 | + |
369 | +logger = logging.getLogger(__name__) |
370 | + |
371 | +# This is a special value that means we use the default channel, which comes |
372 | +# from the charm config. |
373 | +DEFAULT_SNAP_CHANNEL = None |
374 | + |
375 | +APPSTREAM_BASE = Path("~ubuntu/appstream").expanduser() |
376 | +APPSTREAM_PUBLIC = APPSTREAM_BASE / "appstream-public" |
377 | +APPSTREAM_WORKDIR = APPSTREAM_BASE / "appstream-workdir" |
378 | +ENVIRONMENT_FILE = Path("/etc/environment.d/proxy.conf") |
379 | +INPUT_FILENAME = "asgen-config.json.in" |
380 | +OUTPUT_FILENAME = APPSTREAM_WORKDIR / "asgen-config.json" |
381 | +PACKAGES_TO_INSTALL = ["jq"] |
382 | +SNAPS_TO_INSTALL = {"appstream-generator": DEFAULT_SNAP_CHANNEL} |
383 | +SYSTEMD_ENABLE_UNITS = ("appstream-generator.timer",) |
384 | +SYSTEMD_UNITS = ("appstream-generator.service", "appstream-generator.timer") |
385 | + |
386 | +CONFIG_DEFAULT_PRIORITY = 0 |
387 | + |
388 | +CONFIG_PRIORITIES = { |
389 | + "updates": 10, |
390 | + "security": 20, |
391 | + "proposed": 30, |
392 | + "backports": 40, |
393 | +} |
394 | + |
395 | +CONFIG_HEADER = { |
396 | + "ProjectName": "Ubuntu", |
397 | + "Backend": "ubuntu", |
398 | + "Oldsuites": [], |
399 | + "Suites": {}, |
400 | + "Features": {"validateMetainfo": True}, |
401 | +} |
402 | + |
403 | + |
404 | +class AppstreamGeneratorCharm(CharmBase): |
405 | + _stored = StoredState() |
406 | + |
407 | + def __init__(self, *args): |
408 | + super().__init__(*args) |
409 | + |
410 | + self.framework.observe(self.on.config_changed, self._on_config_changed) |
411 | + self.framework.observe(self.on.install, self._on_install) |
412 | + self.framework.observe( |
413 | + self.on.appstream_storage_attached, |
414 | + self._on_appstream_storage_attached, |
415 | + ) |
416 | + self.framework.observe( |
417 | + self.on.appstream_storage_detaching, |
418 | + self._on_appstream_storage_detaching, |
419 | + ) |
420 | + self.framework.observe(self.on.start, self._on_start) |
421 | + self.framework.observe(self.on.clean_action, self._on_clean_action) |
422 | + self.framework.observe(self.on.forget_action, self._on_forget_action) |
423 | + self.framework.observe( |
424 | + self.on.forget_tag_action, self._on_forget_tag_action |
425 | + ) |
426 | + |
427 | + self._stored.set_default( |
428 | + installed_packages=set(), |
429 | + installed_snaps=dict(), |
430 | + storage_attached=False, |
431 | + ) |
432 | + |
433 | + def _on_clean_action(self, event): |
434 | + clean_file = APPSTREAM_BASE / "clean" |
435 | + with clean_file.open("w") as f: |
436 | + pass |
437 | + shutil.chown(clean_file, user="ubuntu", group="ubuntu") |
438 | + logger.info("Data will be cleaned with the next full run.") |
439 | + |
440 | + def _on_forget_action(self, event): |
441 | + forget_file = APPSTREAM_BASE / "forget" |
442 | + packages_raw = event.params["packages"] |
443 | + packages = json.loads(packages_raw) |
444 | + packages_s = ", ".join(packages) |
445 | + logger.info(f"Forgetting {packages_s}") |
446 | + with forget_file.open("a") as f: |
447 | + for package in packages: |
448 | + f.write(f"{package}\n") |
449 | + |
450 | + def _on_forget_tag_action(self, event): |
451 | + import lzma |
452 | + |
453 | + forget_file = APPSTREAM_BASE / "forget" |
454 | + hints_files = (APPSTREAM_PUBLIC / "hints").glob("*/*/Hints-*.xz") |
455 | + tag_to_forget = event.params["tag"] |
456 | + logger.info(f"Forgetting all packages with tag {tag_to_forget}") |
457 | + |
458 | + for filename in hints_files: |
459 | + p = set() |
460 | + hf = lzma.open(filename, "rt", encoding="utf-8") |
461 | + j = json.load(hf) |
462 | + for (v, pkg) in [ |
463 | + (v, pkg) |
464 | + for (d, pkg) in [(t["hints"], t["package"]) for t in j] |
465 | + for v in d.values() |
466 | + ]: |
467 | + for i in v: |
468 | + if i["tag"] == tag_to_forget: |
469 | + p.add(pkg) |
470 | + |
471 | + with forget_file.open("a") as f: |
472 | + for pkg in p: |
473 | + f.write(f"{pkg}\n") |
474 | + |
475 | + def _on_appstream_storage_attached(self, event): |
476 | + self._stored.storage_attached = True |
477 | + mp = self.meta.storages["appstream"].location |
478 | + shutil.chown(mp, user="ubuntu", group="ubuntu") |
479 | + try: |
480 | + APPSTREAM_WORKDIR.mkdir(parents=True, exist_ok=False) |
481 | + shutil.chown(APPSTREAM_WORKDIR, user="ubuntu", group="ubuntu") |
482 | + except FileExistsError: |
483 | + pass |
484 | + |
485 | + def _on_appstream_storage_detaching(self, _): |
486 | + self._stored.storage_attached = False |
487 | + |
488 | + def _on_start(self, event): |
489 | + if not self._ensure_set_up(event, more_to_do=True): |
490 | + return |
491 | + |
492 | + for unit in SYSTEMD_ENABLE_UNITS: |
493 | + subprocess.check_call( |
494 | + ["systemctl", "enable", "--quiet", "--now", unit] |
495 | + ) |
496 | + self.unit.status = ActiveStatus() |
497 | + |
498 | + def _install_packages(self, packages): |
499 | + packages = packages - self._stored.installed_packages |
500 | + if not packages: |
501 | + logger.info("No packages to install.") |
502 | + return |
503 | + pkgs = ", ".join(packages) |
504 | + self.unit.status = MaintenanceStatus(f"Installing {pkgs}") |
505 | + logger.info(f"Installing apt package(s) {pkgs}") |
506 | + subprocess.check_call( |
507 | + [ |
508 | + "apt-get", |
509 | + "--assume-yes", |
510 | + "--option=Dpkg::Options::=--force-confold", |
511 | + "install", |
512 | + ] |
513 | + + list(packages) |
514 | + ) |
515 | + self._stored.installed_packages |= packages |
516 | + |
517 | + def _install_snaps(self, wanted_snaps): |
518 | + default_snap_channel = self.model.config.get( |
519 | + "default_snap_channel", "stable" |
520 | + ) |
521 | + snaps_to_install = {} |
522 | + for snap in wanted_snaps: |
523 | + wanted_channel = wanted_snaps[snap] or default_snap_channel |
524 | + if snap not in self._stored.installed_snaps: |
525 | + verb = "install" |
526 | + else: |
527 | + if self._stored.installed_snaps[snap] == wanted_channel: |
528 | + continue |
529 | + verb = "refresh" |
530 | + snaps_to_install[snap] = wanted_channel, verb |
531 | + |
532 | + if not snaps_to_install: |
533 | + logger.info("No snaps to install.") |
534 | + return |
535 | + snps_install = ", ".join( |
536 | + [ |
537 | + s |
538 | + for s in snaps_to_install |
539 | + if snaps_to_install[s][1] == "install" |
540 | + ] |
541 | + ) |
542 | + status_list = [] |
543 | + if snps_install: |
544 | + status_list.append(f"Installing snap packages: {snps_install}") |
545 | + snps_refresh = ", ".join( |
546 | + [ |
547 | + f"{s}/{snaps_to_install[s][0]}" |
548 | + for s in snaps_to_install |
549 | + if snaps_to_install[s][1] == "refresh" |
550 | + ] |
551 | + ) |
552 | + if snps_refresh: |
553 | + status_list.append(f"Refreshing snap packages: {snps_refresh}") |
554 | + status_string = "; ".join(status_list) |
555 | + |
556 | + self.unit.status = MaintenanceStatus(status_string) |
557 | + logger.info(status_string) |
558 | + for snap, (channel, verb) in snaps_to_install.items(): |
559 | + subprocess.check_call( |
560 | + [ |
561 | + "snap", |
562 | + verb, |
563 | + "--channel", |
564 | + channel, |
565 | + snap, |
566 | + ], |
567 | + ) |
568 | + self._stored.installed_snaps[snap] = channel |
569 | + |
570 | + def _set_up_proxy(self): |
571 | + http_proxy = self.model.config.get("http-proxy") |
572 | + https_proxy = self.model.config.get("https-proxy") |
573 | + no_proxy = self.model.config.get("no-proxy") |
574 | + |
575 | + if http_proxy or https_proxy or no_proxy: |
576 | + logger.info(f"Writing proxy settings to {ENVIRONMENT_FILE}") |
577 | + ENVIRONMENT_FILE.mkdir(parents=True, exist_ok=True) |
578 | + with ENVIRONMENT_FILE.open("w") as env: |
579 | + if http_proxy: |
580 | + env.write(f"http_proxy={http_proxy}\n") |
581 | + if https_proxy: |
582 | + env.write(f"https_proxy={https_proxy}\n") |
583 | + if no_proxy: |
584 | + env.write(f"no_proxy={no_proxy}\n") |
585 | + else: |
586 | + try: |
587 | + os.unlink(ENVIRONMENT_FILE) |
588 | + except FileNotFoundError: |
589 | + pass |
590 | + |
591 | + def _config_process_suite( |
592 | + self, release, info, default_arches, default_suites |
593 | + ): |
594 | + out = {} |
595 | + for suite in ( |
596 | + "%s%s" % (release, s) for s in info.get("suites", default_suites) |
597 | + ): |
598 | + out[suite] = { |
599 | + "useIconTheme": "Humanity", |
600 | + "dataPriority": CONFIG_PRIORITIES.get( |
601 | + suite.split("-")[-1], CONFIG_DEFAULT_PRIORITY |
602 | + ), |
603 | + "sections": ["main", "universe", "multiverse", "restricted"], |
604 | + "architectures": info.get("architectures", default_arches), |
605 | + } |
606 | + if suite != release: |
607 | + out[suite]["baseSuite"] = release |
608 | + try: |
609 | + # if we have 'released' : true, make the base suite immutable |
610 | + info["released"] |
611 | + out[release]["immutable"] = True |
612 | + except KeyError: |
613 | + pass |
614 | + |
615 | + return out |
616 | + |
617 | + def _write_config(self): |
618 | + mirror = self.model.config.get("mirror") |
619 | + hostname = self.model.config.get("hostname") |
620 | + config = self.model.config.get("config") |
621 | + |
622 | + if not (mirror and hostname and config): |
623 | + logger.info("No config set. Can't continue.") |
624 | + return False |
625 | + |
626 | + config_j = json.loads(config) |
627 | + |
628 | + # Read the defaults |
629 | + default_arches = config_j["default"]["architectures"] |
630 | + default_suites = config_j["default"]["suites"] |
631 | + del config_j["default"] |
632 | + |
633 | + o = CONFIG_HEADER |
634 | + o["ArchiveRoot"] = mirror |
635 | + o["MediaBaseUrl"] = f"{hostname}/media" |
636 | + o["HtmlBaseUrl"] = hostname |
637 | + |
638 | + # Now do the rest |
639 | + for (release, ting) in config_j.items(): |
640 | + if ting.get("oldSuite", False): |
641 | + CONFIG_HEADER["Oldsuites"].append(release) |
642 | + o["Suites"].update( |
643 | + self._config_process_suite( |
644 | + release, ting, default_arches, default_suites |
645 | + ) |
646 | + ) |
647 | + |
648 | + OUTPUT_FILENAME.parent.mkdir(parents=True, exist_ok=True) |
649 | + with OUTPUT_FILENAME.open("w") as f: |
650 | + f.write(json.dumps(o, indent=4, sort_keys=True)) |
651 | + shutil.chown(OUTPUT_FILENAME, user="ubuntu", group="ubuntu") |
652 | + |
653 | + return True |
654 | + |
655 | + def _symlink_systemd_units(self): |
656 | + any_changed = False |
657 | + unit_dir = Path("/etc/systemd/system") |
658 | + charm_dir = Path(self.charm_dir) |
659 | + |
660 | + for unit in SYSTEMD_UNITS: |
661 | + dest = unit_dir / unit |
662 | + try: |
663 | + target = charm_dir / "units" / unit |
664 | + dest.symlink_to(target) |
665 | + any_changed = True |
666 | + logger.info(f"Symlinking {dest} → {target}") |
667 | + except FileExistsError: |
668 | + if dest.resolve() != target.resolve(): |
669 | + logger.info( |
670 | + f"Target for {dest} has changed to {target}. Re-creating." |
671 | + ) |
672 | + dest.unlink() |
673 | + dest.symlink_to(target) |
674 | + any_changed = True |
675 | + |
676 | + if any_changed: |
677 | + subprocess.check_call(["systemctl", "daemon-reload"]) |
678 | + |
679 | + def _symlink_scripts(self): |
680 | + home = Path("~ubuntu").expanduser() |
681 | + scripts_dir = Path(self.charm_dir) / "scripts" |
682 | + |
683 | + for script in scripts_dir.glob("*"): |
684 | + if script.is_dir(): |
685 | + continue |
686 | + dest = home / script.name |
687 | + try: |
688 | + dest.symlink_to(script) |
689 | + logger.info(f"Symlinking {dest} → {script}") |
690 | + except FileExistsError: |
691 | + pass |
692 | + |
693 | + def _set_up_rsync(self): |
694 | + any_written = False |
695 | + rsync_conf = Path("/etc/rsyncd.conf") |
696 | + rsync_d = Path("/etc/rsync-juju.d/") |
697 | + names_paths = ( |
698 | + ("appstream", APPSTREAM_PUBLIC / "data"), |
699 | + ("www", APPSTREAM_PUBLIC), |
700 | + ("logs", APPSTREAM_BASE / "logs"), |
701 | + ) |
702 | + rsync_template = dedent( |
703 | + """[{name}] |
704 | + path = {path} |
705 | + read only = yes |
706 | + list = yes |
707 | + uid = ubuntu |
708 | + gid = ubuntu |
709 | + chroot = false |
710 | + """ |
711 | + ) |
712 | + |
713 | + try: |
714 | + # XXX: This means if we change the template, changes will not be |
715 | + # written to the output file. |
716 | + with rsync_conf.open("x") as f: |
717 | + f.write( |
718 | + dedent( |
719 | + """ |
720 | + uid = nobody |
721 | + gid = nogroup |
722 | + pid file = /var/run/rsyncd.pid |
723 | + syslog facility = daemon |
724 | + socket options = SO_KEEPALIVE |
725 | + timeout = 7200 |
726 | + |
727 | + &include /etc/rsync-juju.d |
728 | + """ |
729 | + ) |
730 | + ) |
731 | + except FileExistsError: |
732 | + pass |
733 | + |
734 | + rsync_d.mkdir(parents=True, exist_ok=True) |
735 | + |
736 | + for name, path in names_paths: |
737 | + path.mkdir(parents=True, exist_ok=True) |
738 | + try: |
739 | + # XXX: This means if we change the template above, changes will |
740 | + # not be written to the output file. |
741 | + conf = rsync_d / f"{name}.conf" |
742 | + with conf.open("x") as f: |
743 | + logger.info(f"Writing rsync config to {conf}") |
744 | + f.write(rsync_template.format(name=name, path=path)) |
745 | + any_written = True |
746 | + except FileExistsError: |
747 | + pass |
748 | + |
749 | + if any_written: |
750 | + subprocess.check_call(["systemctl", "restart", "rsync"]) |
751 | + open_port(873) |
752 | + |
753 | + def _ensure_set_up(self, event, more_to_do=False): |
754 | + if not self._stored.storage_attached: |
755 | + event.defer() |
756 | + self.unit.status = BlockedStatus( |
757 | + "Waiting for storage to become attached." |
758 | + ) |
759 | + return False |
760 | + |
761 | + self._install_packages(set(PACKAGES_TO_INSTALL)) |
762 | + self._install_snaps(SNAPS_TO_INSTALL) |
763 | + self._set_up_proxy() |
764 | + self._symlink_systemd_units() |
765 | + self._symlink_scripts() |
766 | + self._set_up_rsync() |
767 | + |
768 | + if not self._write_config(): |
769 | + logger.info("Failed to write config. Blocked.") |
770 | + event.defer() |
771 | + self.unit.status = BlockedStatus( |
772 | + "Config not set. Make sure config, hostname and mirror are set." |
773 | + ) |
774 | + return False |
775 | + |
776 | + if not more_to_do: |
777 | + self.unit.status = ActiveStatus() |
778 | + return True |
779 | + |
780 | + def _on_install(self, event): |
781 | + # We're not started yet, so don't set active. We'll do that after the |
782 | + # `start` hook. |
783 | + self._ensure_set_up(event, more_to_do=True) |
784 | + |
785 | + def _on_config_changed(self, event): |
786 | + if "appstream-generator" not in self._stored.installed_snaps: |
787 | + event.defer() |
788 | + return |
789 | + |
790 | + self._ensure_set_up(event) |
791 | + |
792 | + |
793 | +if __name__ == "__main__": |
794 | + main(AppstreamGeneratorCharm) |
795 | diff --git a/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/INSTALLER b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/INSTALLER |
796 | new file mode 100644 |
797 | index 0000000..a1b589e |
798 | --- /dev/null |
799 | +++ b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/INSTALLER |
800 | @@ -0,0 +1 @@ |
801 | +pip |
802 | diff --git a/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/LICENSE.rst b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/LICENSE.rst |
803 | new file mode 100644 |
804 | index 0000000..c37cae4 |
805 | --- /dev/null |
806 | +++ b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/LICENSE.rst |
807 | @@ -0,0 +1,28 @@ |
808 | +Copyright 2007 Pallets |
809 | + |
810 | +Redistribution and use in source and binary forms, with or without |
811 | +modification, are permitted provided that the following conditions are |
812 | +met: |
813 | + |
814 | +1. Redistributions of source code must retain the above copyright |
815 | + notice, this list of conditions and the following disclaimer. |
816 | + |
817 | +2. Redistributions in binary form must reproduce the above copyright |
818 | + notice, this list of conditions and the following disclaimer in the |
819 | + documentation and/or other materials provided with the distribution. |
820 | + |
821 | +3. Neither the name of the copyright holder nor the names of its |
822 | + contributors may be used to endorse or promote products derived from |
823 | + this software without specific prior written permission. |
824 | + |
825 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
826 | +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
827 | +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
828 | +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
829 | +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
830 | +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
831 | +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
832 | +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
833 | +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
834 | +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
835 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
836 | diff --git a/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/METADATA b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/METADATA |
837 | new file mode 100644 |
838 | index 0000000..274e91c |
839 | --- /dev/null |
840 | +++ b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/METADATA |
841 | @@ -0,0 +1,113 @@ |
842 | +Metadata-Version: 2.1 |
843 | +Name: Jinja2 |
844 | +Version: 3.0.2 |
845 | +Summary: A very fast and expressive template engine. |
846 | +Home-page: https://palletsprojects.com/p/jinja/ |
847 | +Author: Armin Ronacher |
848 | +Author-email: armin.ronacher@active-4.com |
849 | +Maintainer: Pallets |
850 | +Maintainer-email: contact@palletsprojects.com |
851 | +License: BSD-3-Clause |
852 | +Project-URL: Donate, https://palletsprojects.com/donate |
853 | +Project-URL: Documentation, https://jinja.palletsprojects.com/ |
854 | +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ |
855 | +Project-URL: Source Code, https://github.com/pallets/jinja/ |
856 | +Project-URL: Issue Tracker, https://github.com/pallets/jinja/issues/ |
857 | +Project-URL: Twitter, https://twitter.com/PalletsTeam |
858 | +Project-URL: Chat, https://discord.gg/pallets |
859 | +Platform: UNKNOWN |
860 | +Classifier: Development Status :: 5 - Production/Stable |
861 | +Classifier: Environment :: Web Environment |
862 | +Classifier: Intended Audience :: Developers |
863 | +Classifier: License :: OSI Approved :: BSD License |
864 | +Classifier: Operating System :: OS Independent |
865 | +Classifier: Programming Language :: Python |
866 | +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content |
867 | +Classifier: Topic :: Text Processing :: Markup :: HTML |
868 | +Requires-Python: >=3.6 |
869 | +Description-Content-Type: text/x-rst |
870 | +License-File: LICENSE.rst |
871 | +Requires-Dist: MarkupSafe (>=2.0) |
872 | +Provides-Extra: i18n |
873 | +Requires-Dist: Babel (>=2.7) ; extra == 'i18n' |
874 | + |
875 | +Jinja |
876 | +===== |
877 | + |
878 | +Jinja is a fast, expressive, extensible templating engine. Special |
879 | +placeholders in the template allow writing code similar to Python |
880 | +syntax. Then the template is passed data to render the final document. |
881 | + |
882 | +It includes: |
883 | + |
884 | +- Template inheritance and inclusion. |
885 | +- Define and import macros within templates. |
886 | +- HTML templates can use autoescaping to prevent XSS from untrusted |
887 | + user input. |
888 | +- A sandboxed environment can safely render untrusted templates. |
889 | +- AsyncIO support for generating templates and calling async |
890 | + functions. |
891 | +- I18N support with Babel. |
892 | +- Templates are compiled to optimized Python code just-in-time and |
893 | + cached, or can be compiled ahead-of-time. |
894 | +- Exceptions point to the correct line in templates to make debugging |
895 | + easier. |
896 | +- Extensible filters, tests, functions, and even syntax. |
897 | + |
898 | +Jinja's philosophy is that while application logic belongs in Python if |
899 | +possible, it shouldn't make the template designer's job difficult by |
900 | +restricting functionality too much. |
901 | + |
902 | + |
903 | +Installing |
904 | +---------- |
905 | + |
906 | +Install and update using `pip`_: |
907 | + |
908 | +.. code-block:: text |
909 | + |
910 | + $ pip install -U Jinja2 |
911 | + |
912 | +.. _pip: https://pip.pypa.io/en/stable/getting-started/ |
913 | + |
914 | + |
915 | +In A Nutshell |
916 | +------------- |
917 | + |
918 | +.. code-block:: jinja |
919 | + |
920 | + {% extends "base.html" %} |
921 | + {% block title %}Members{% endblock %} |
922 | + {% block content %} |
923 | + <ul> |
924 | + {% for user in users %} |
925 | + <li><a href="{{ user.url }}">{{ user.username }}</a></li> |
926 | + {% endfor %} |
927 | + </ul> |
928 | + {% endblock %} |
929 | + |
930 | + |
931 | +Donate |
932 | +------ |
933 | + |
934 | +The Pallets organization develops and supports Jinja and other popular |
935 | +packages. In order to grow the community of contributors and users, and |
936 | +allow the maintainers to devote more time to the projects, `please |
937 | +donate today`_. |
938 | + |
939 | +.. _please donate today: https://palletsprojects.com/donate |
940 | + |
941 | + |
942 | +Links |
943 | +----- |
944 | + |
945 | +- Documentation: https://jinja.palletsprojects.com/ |
946 | +- Changes: https://jinja.palletsprojects.com/changes/ |
947 | +- PyPI Releases: https://pypi.org/project/Jinja2/ |
948 | +- Source Code: https://github.com/pallets/jinja/ |
949 | +- Issue Tracker: https://github.com/pallets/jinja/issues/ |
950 | +- Website: https://palletsprojects.com/p/jinja/ |
951 | +- Twitter: https://twitter.com/PalletsTeam |
952 | +- Chat: https://discord.gg/pallets |
953 | + |
954 | + |
955 | diff --git a/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/RECORD b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/RECORD |
956 | new file mode 100644 |
957 | index 0000000..7438108 |
958 | --- /dev/null |
959 | +++ b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/RECORD |
960 | @@ -0,0 +1,58 @@ |
961 | +Jinja2-3.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 |
962 | +Jinja2-3.0.2.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 |
963 | +Jinja2-3.0.2.dist-info/METADATA,sha256=NxKriGP-LwQjFBZ4hjV696NkZMe3GPy3tE00McDQZZ0,3539 |
964 | +Jinja2-3.0.2.dist-info/RECORD,, |
965 | +Jinja2-3.0.2.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92 |
966 | +Jinja2-3.0.2.dist-info/entry_points.txt,sha256=Qy_DkVo6Xj_zzOtmErrATe8lHZhOqdjpt3e4JJAGyi8,61 |
967 | +Jinja2-3.0.2.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 |
968 | +jinja2/__init__.py,sha256=w4sanG5_dogKC4J_2thsPN9tXzmily3fmXK8Pd46Q1Y,2205 |
969 | +jinja2/__pycache__/__init__.cpython-38.pyc,, |
970 | +jinja2/__pycache__/_identifier.cpython-38.pyc,, |
971 | +jinja2/__pycache__/async_utils.cpython-38.pyc,, |
972 | +jinja2/__pycache__/bccache.cpython-38.pyc,, |
973 | +jinja2/__pycache__/compiler.cpython-38.pyc,, |
974 | +jinja2/__pycache__/constants.cpython-38.pyc,, |
975 | +jinja2/__pycache__/debug.cpython-38.pyc,, |
976 | +jinja2/__pycache__/defaults.cpython-38.pyc,, |
977 | +jinja2/__pycache__/environment.cpython-38.pyc,, |
978 | +jinja2/__pycache__/exceptions.cpython-38.pyc,, |
979 | +jinja2/__pycache__/ext.cpython-38.pyc,, |
980 | +jinja2/__pycache__/filters.cpython-38.pyc,, |
981 | +jinja2/__pycache__/idtracking.cpython-38.pyc,, |
982 | +jinja2/__pycache__/lexer.cpython-38.pyc,, |
983 | +jinja2/__pycache__/loaders.cpython-38.pyc,, |
984 | +jinja2/__pycache__/meta.cpython-38.pyc,, |
985 | +jinja2/__pycache__/nativetypes.cpython-38.pyc,, |
986 | +jinja2/__pycache__/nodes.cpython-38.pyc,, |
987 | +jinja2/__pycache__/optimizer.cpython-38.pyc,, |
988 | +jinja2/__pycache__/parser.cpython-38.pyc,, |
989 | +jinja2/__pycache__/runtime.cpython-38.pyc,, |
990 | +jinja2/__pycache__/sandbox.cpython-38.pyc,, |
991 | +jinja2/__pycache__/tests.cpython-38.pyc,, |
992 | +jinja2/__pycache__/utils.cpython-38.pyc,, |
993 | +jinja2/__pycache__/visitor.cpython-38.pyc,, |
994 | +jinja2/_identifier.py,sha256=EdgGJKi7O1yvr4yFlvqPNEqV6M1qHyQr8Gt8GmVTKVM,1775 |
995 | +jinja2/async_utils.py,sha256=bY2nCUfBA_4FSnNUsIsJgljBq3hACr6fzLi7LiyMTn8,1751 |
996 | +jinja2/bccache.py,sha256=v5rKAlYxIvfJEa0uGzAC6yCYSS3KuXT5Eqi-n9qvNi8,12670 |
997 | +jinja2/compiler.py,sha256=v7zKz-mgSYXmfXD9mRmi2BU0B6Z-1RGZmOXCrsPKzc0,72209 |
998 | +jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 |
999 | +jinja2/debug.py,sha256=uBmrsiwjYH5l14R9STn5mydOOyriBYol5lDGvEqAb3A,9238 |
1000 | +jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 |
1001 | +jinja2/environment.py,sha256=T6U4be9mY1CUXXin_EQFwpvpFqCiryweGqzXGRYIoSA,61573 |
1002 | +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 |
1003 | +jinja2/ext.py,sha256=44SjDjeYkkxQTpmC2BetOTxEFMgQ42p2dfSwXmPFcSo,32122 |
1004 | +jinja2/filters.py,sha256=jusKTZbd0ddZMaibZkxMUVKNsOsaYtOq_Il8Imtx4BE,52609 |
1005 | +jinja2/idtracking.py,sha256=WekexMql3u5n3vDxFsQ_i8HW0j24AtjWTjrPBLWrHww,10721 |
1006 | +jinja2/lexer.py,sha256=qNEQqDQw_zO5EaH6rFQsER7Qwn2du0o22prB-TR11HE,29930 |
1007 | +jinja2/loaders.py,sha256=WGJNP5RQEGtuTABIK2tp1sWEy2kfe5ZFOY0ON0gi0LY,22477 |
1008 | +jinja2/meta.py,sha256=GNPEvifmSaU3CMxlbheBOZjeZ277HThOPUTf1RkppKQ,4396 |
1009 | +jinja2/nativetypes.py,sha256=62hvvsAxAj0YaxylOHoREYVogJ5JqOlJISgGY3OKd_o,3675 |
1010 | +jinja2/nodes.py,sha256=8zvzM5mYaylI-kbT6oI1DChxGH8dZkghWt1fVizy4Us,34605 |
1011 | +jinja2/optimizer.py,sha256=tHkMwXxfZkbfA1KmLcqmBMSaz7RLIvvItrJcPoXTyD8,1650 |
1012 | +jinja2/parser.py,sha256=kHnU8v92GwMYkfr0MVakWv8UlSf_kJPx8LUsgQMof70,39767 |
1013 | +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 |
1014 | +jinja2/runtime.py,sha256=wVRlkEmAgNU67AIQDqLvI6UkNLkzDqpLA-z4Mi3vl3g,35054 |
1015 | +jinja2/sandbox.py,sha256=-8zxR6TO9kUkciAVFsIKu8Oq-C7PTeYEdZ5TtA55-gw,14600 |
1016 | +jinja2/tests.py,sha256=Am5Z6Lmfr2XaH_npIfJJ8MdXtWsbLjMULZJulTAj30E,5905 |
1017 | +jinja2/utils.py,sha256=udQxWIKaq4QDCZiXN31ngKOaGGdaMA5fl0JMaM-F6fg,26971 |
1018 | +jinja2/visitor.py,sha256=ZmeLuTj66ic35-uFH-1m0EKXiw4ObDDb_WuE6h5vPFg,3572 |
1019 | diff --git a/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/WHEEL b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/WHEEL |
1020 | new file mode 100644 |
1021 | index 0000000..5bad85f |
1022 | --- /dev/null |
1023 | +++ b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/WHEEL |
1024 | @@ -0,0 +1,5 @@ |
1025 | +Wheel-Version: 1.0 |
1026 | +Generator: bdist_wheel (0.37.0) |
1027 | +Root-Is-Purelib: true |
1028 | +Tag: py3-none-any |
1029 | + |
1030 | diff --git a/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/entry_points.txt b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/entry_points.txt |
1031 | new file mode 100644 |
1032 | index 0000000..3619483 |
1033 | --- /dev/null |
1034 | +++ b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/entry_points.txt |
1035 | @@ -0,0 +1,3 @@ |
1036 | +[babel.extractors] |
1037 | +jinja2 = jinja2.ext:babel_extract [i18n] |
1038 | + |
1039 | diff --git a/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/top_level.txt b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/top_level.txt |
1040 | new file mode 100644 |
1041 | index 0000000..7f7afbf |
1042 | --- /dev/null |
1043 | +++ b/charms/appstream-generator/venv/Jinja2-3.0.2.dist-info/top_level.txt |
1044 | @@ -0,0 +1 @@ |
1045 | +jinja2 |
1046 | diff --git a/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/INSTALLER b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/INSTALLER |
1047 | new file mode 100644 |
1048 | index 0000000..a1b589e |
1049 | --- /dev/null |
1050 | +++ b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/INSTALLER |
1051 | @@ -0,0 +1 @@ |
1052 | +pip |
1053 | diff --git a/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/LICENSE.rst b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/LICENSE.rst |
1054 | new file mode 100644 |
1055 | index 0000000..9d227a0 |
1056 | --- /dev/null |
1057 | +++ b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/LICENSE.rst |
1058 | @@ -0,0 +1,28 @@ |
1059 | +Copyright 2010 Pallets |
1060 | + |
1061 | +Redistribution and use in source and binary forms, with or without |
1062 | +modification, are permitted provided that the following conditions are |
1063 | +met: |
1064 | + |
1065 | +1. Redistributions of source code must retain the above copyright |
1066 | + notice, this list of conditions and the following disclaimer. |
1067 | + |
1068 | +2. Redistributions in binary form must reproduce the above copyright |
1069 | + notice, this list of conditions and the following disclaimer in the |
1070 | + documentation and/or other materials provided with the distribution. |
1071 | + |
1072 | +3. Neither the name of the copyright holder nor the names of its |
1073 | + contributors may be used to endorse or promote products derived from |
1074 | + this software without specific prior written permission. |
1075 | + |
1076 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
1077 | +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
1078 | +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
1079 | +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
1080 | +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
1081 | +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
1082 | +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
1083 | +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
1084 | +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
1085 | +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
1086 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
1087 | diff --git a/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/METADATA b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/METADATA |
1088 | new file mode 100644 |
1089 | index 0000000..ef44e2b |
1090 | --- /dev/null |
1091 | +++ b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/METADATA |
1092 | @@ -0,0 +1,100 @@ |
1093 | +Metadata-Version: 2.1 |
1094 | +Name: MarkupSafe |
1095 | +Version: 2.0.1 |
1096 | +Summary: Safely add untrusted strings to HTML/XML markup. |
1097 | +Home-page: https://palletsprojects.com/p/markupsafe/ |
1098 | +Author: Armin Ronacher |
1099 | +Author-email: armin.ronacher@active-4.com |
1100 | +Maintainer: Pallets |
1101 | +Maintainer-email: contact@palletsprojects.com |
1102 | +License: BSD-3-Clause |
1103 | +Project-URL: Donate, https://palletsprojects.com/donate |
1104 | +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ |
1105 | +Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ |
1106 | +Project-URL: Source Code, https://github.com/pallets/markupsafe/ |
1107 | +Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/ |
1108 | +Project-URL: Twitter, https://twitter.com/PalletsTeam |
1109 | +Project-URL: Chat, https://discord.gg/pallets |
1110 | +Platform: UNKNOWN |
1111 | +Classifier: Development Status :: 5 - Production/Stable |
1112 | +Classifier: Environment :: Web Environment |
1113 | +Classifier: Intended Audience :: Developers |
1114 | +Classifier: License :: OSI Approved :: BSD License |
1115 | +Classifier: Operating System :: OS Independent |
1116 | +Classifier: Programming Language :: Python |
1117 | +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content |
1118 | +Classifier: Topic :: Text Processing :: Markup :: HTML |
1119 | +Requires-Python: >=3.6 |
1120 | +Description-Content-Type: text/x-rst |
1121 | + |
1122 | +MarkupSafe |
1123 | +========== |
1124 | + |
1125 | +MarkupSafe implements a text object that escapes characters so it is |
1126 | +safe to use in HTML and XML. Characters that have special meanings are |
1127 | +replaced so that they display as the actual characters. This mitigates |
1128 | +injection attacks, meaning untrusted user input can safely be displayed |
1129 | +on a page. |
1130 | + |
1131 | + |
1132 | +Installing |
1133 | +---------- |
1134 | + |
1135 | +Install and update using `pip`_: |
1136 | + |
1137 | +.. code-block:: text |
1138 | + |
1139 | + pip install -U MarkupSafe |
1140 | + |
1141 | +.. _pip: https://pip.pypa.io/en/stable/quickstart/ |
1142 | + |
1143 | + |
1144 | +Examples |
1145 | +-------- |
1146 | + |
1147 | +.. code-block:: pycon |
1148 | + |
1149 | + >>> from markupsafe import Markup, escape |
1150 | + |
1151 | + >>> # escape replaces special characters and wraps in Markup |
1152 | + >>> escape("<script>alert(document.cookie);</script>") |
1153 | + Markup('<script>alert(document.cookie);</script>') |
1154 | + |
1155 | + >>> # wrap in Markup to mark text "safe" and prevent escaping |
1156 | + >>> Markup("<strong>Hello</strong>") |
1157 | + Markup('<strong>hello</strong>') |
1158 | + |
1159 | + >>> escape(Markup("<strong>Hello</strong>")) |
1160 | + Markup('<strong>hello</strong>') |
1161 | + |
1162 | + >>> # Markup is a str subclass |
1163 | + >>> # methods and operators escape their arguments |
1164 | + >>> template = Markup("Hello <em>{name}</em>") |
1165 | + >>> template.format(name='"World"') |
1166 | + Markup('Hello <em>"World"</em>') |
1167 | + |
1168 | + |
1169 | +Donate |
1170 | +------ |
1171 | + |
1172 | +The Pallets organization develops and supports MarkupSafe and other |
1173 | +popular packages. In order to grow the community of contributors and |
1174 | +users, and allow the maintainers to devote more time to the projects, |
1175 | +`please donate today`_. |
1176 | + |
1177 | +.. _please donate today: https://palletsprojects.com/donate |
1178 | + |
1179 | + |
1180 | +Links |
1181 | +----- |
1182 | + |
1183 | +- Documentation: https://markupsafe.palletsprojects.com/ |
1184 | +- Changes: https://markupsafe.palletsprojects.com/changes/ |
1185 | +- PyPI Releases: https://pypi.org/project/MarkupSafe/ |
1186 | +- Source Code: https://github.com/pallets/markupsafe/ |
1187 | +- Issue Tracker: https://github.com/pallets/markupsafe/issues/ |
1188 | +- Website: https://palletsprojects.com/p/markupsafe/ |
1189 | +- Twitter: https://twitter.com/PalletsTeam |
1190 | +- Chat: https://discord.gg/pallets |
1191 | + |
1192 | + |
1193 | diff --git a/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/RECORD b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/RECORD |
1194 | new file mode 100644 |
1195 | index 0000000..768efa3 |
1196 | --- /dev/null |
1197 | +++ b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/RECORD |
1198 | @@ -0,0 +1,14 @@ |
1199 | +MarkupSafe-2.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 |
1200 | +MarkupSafe-2.0.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 |
1201 | +MarkupSafe-2.0.1.dist-info/METADATA,sha256=FmPpxBdaqCCjF-XKqoxeEzqAzhetQnrkkSsd3V3X-Jc,3211 |
1202 | +MarkupSafe-2.0.1.dist-info/RECORD,, |
1203 | +MarkupSafe-2.0.1.dist-info/WHEEL,sha256=RIeRBYNNiNK3sXfnenIjXDrR2Tzyz05xCMpKF2hJ1iA,111 |
1204 | +MarkupSafe-2.0.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 |
1205 | +markupsafe/__init__.py,sha256=9Tez4UIlI7J6_sQcUFK1dKniT_b_8YefpGIyYJ3Sr2Q,8923 |
1206 | +markupsafe/__pycache__/__init__.cpython-38.pyc,, |
1207 | +markupsafe/__pycache__/_native.cpython-38.pyc,, |
1208 | +markupsafe/_native.py,sha256=GTKEV-bWgZuSjklhMHOYRHU9k0DMewTf5mVEZfkbuns,1986 |
1209 | +markupsafe/_speedups.c,sha256=CDDtwaV21D2nYtypnMQzxvvpZpcTvIs8OZ6KDa1g4t0,7400 |
1210 | +markupsafe/_speedups.cpython-38-x86_64-linux-gnu.so,sha256=rHWt9NIO4rSSHq0XYjwkiar1C-p7RB198xLDI5Aji0E,53208 |
1211 | +markupsafe/_speedups.pyi,sha256=vfMCsOgbAXRNLUXkyuyonG8uEWKYU4PDqNuMaDELAYw,229 |
1212 | +markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 |
1213 | diff --git a/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/WHEEL b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/WHEEL |
1214 | new file mode 100644 |
1215 | index 0000000..b1fcc33 |
1216 | --- /dev/null |
1217 | +++ b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/WHEEL |
1218 | @@ -0,0 +1,5 @@ |
1219 | +Wheel-Version: 1.0 |
1220 | +Generator: bdist_wheel (0.36.2) |
1221 | +Root-Is-Purelib: false |
1222 | +Tag: cp38-cp38-manylinux2010_x86_64 |
1223 | + |
1224 | diff --git a/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/top_level.txt b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/top_level.txt |
1225 | new file mode 100644 |
1226 | index 0000000..75bf729 |
1227 | --- /dev/null |
1228 | +++ b/charms/appstream-generator/venv/MarkupSafe-2.0.1.dist-info/top_level.txt |
1229 | @@ -0,0 +1 @@ |
1230 | +markupsafe |
1231 | diff --git a/charms/appstream-generator/venv/PyYAML-6.0.dist-info/INSTALLER b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/INSTALLER |
1232 | new file mode 100644 |
1233 | index 0000000..a1b589e |
1234 | --- /dev/null |
1235 | +++ b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/INSTALLER |
1236 | @@ -0,0 +1 @@ |
1237 | +pip |
1238 | diff --git a/charms/appstream-generator/venv/PyYAML-6.0.dist-info/LICENSE b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/LICENSE |
1239 | new file mode 100644 |
1240 | index 0000000..2f1b8e1 |
1241 | --- /dev/null |
1242 | +++ b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/LICENSE |
1243 | @@ -0,0 +1,20 @@ |
1244 | +Copyright (c) 2017-2021 Ingy döt Net |
1245 | +Copyright (c) 2006-2016 Kirill Simonov |
1246 | + |
1247 | +Permission is hereby granted, free of charge, to any person obtaining a copy of |
1248 | +this software and associated documentation files (the "Software"), to deal in |
1249 | +the Software without restriction, including without limitation the rights to |
1250 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
1251 | +of the Software, and to permit persons to whom the Software is furnished to do |
1252 | +so, subject to the following conditions: |
1253 | + |
1254 | +The above copyright notice and this permission notice shall be included in all |
1255 | +copies or substantial portions of the Software. |
1256 | + |
1257 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1258 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1259 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1260 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1261 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1262 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
1263 | +SOFTWARE. |
1264 | diff --git a/charms/appstream-generator/venv/PyYAML-6.0.dist-info/METADATA b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/METADATA |
1265 | new file mode 100644 |
1266 | index 0000000..9a91076 |
1267 | --- /dev/null |
1268 | +++ b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/METADATA |
1269 | @@ -0,0 +1,46 @@ |
1270 | +Metadata-Version: 2.1 |
1271 | +Name: PyYAML |
1272 | +Version: 6.0 |
1273 | +Summary: YAML parser and emitter for Python |
1274 | +Home-page: https://pyyaml.org/ |
1275 | +Author: Kirill Simonov |
1276 | +Author-email: xi@resolvent.net |
1277 | +License: MIT |
1278 | +Download-URL: https://pypi.org/project/PyYAML/ |
1279 | +Project-URL: Bug Tracker, https://github.com/yaml/pyyaml/issues |
1280 | +Project-URL: CI, https://github.com/yaml/pyyaml/actions |
1281 | +Project-URL: Documentation, https://pyyaml.org/wiki/PyYAMLDocumentation |
1282 | +Project-URL: Mailing lists, http://lists.sourceforge.net/lists/listinfo/yaml-core |
1283 | +Project-URL: Source Code, https://github.com/yaml/pyyaml |
1284 | +Platform: Any |
1285 | +Classifier: Development Status :: 5 - Production/Stable |
1286 | +Classifier: Intended Audience :: Developers |
1287 | +Classifier: License :: OSI Approved :: MIT License |
1288 | +Classifier: Operating System :: OS Independent |
1289 | +Classifier: Programming Language :: Cython |
1290 | +Classifier: Programming Language :: Python |
1291 | +Classifier: Programming Language :: Python :: 3 |
1292 | +Classifier: Programming Language :: Python :: 3.6 |
1293 | +Classifier: Programming Language :: Python :: 3.7 |
1294 | +Classifier: Programming Language :: Python :: 3.8 |
1295 | +Classifier: Programming Language :: Python :: 3.9 |
1296 | +Classifier: Programming Language :: Python :: 3.10 |
1297 | +Classifier: Programming Language :: Python :: Implementation :: CPython |
1298 | +Classifier: Programming Language :: Python :: Implementation :: PyPy |
1299 | +Classifier: Topic :: Software Development :: Libraries :: Python Modules |
1300 | +Classifier: Topic :: Text Processing :: Markup |
1301 | +Requires-Python: >=3.6 |
1302 | +License-File: LICENSE |
1303 | + |
1304 | +YAML is a data serialization format designed for human readability |
1305 | +and interaction with scripting languages. PyYAML is a YAML parser |
1306 | +and emitter for Python. |
1307 | + |
1308 | +PyYAML features a complete YAML 1.1 parser, Unicode support, pickle |
1309 | +support, capable extension API, and sensible error messages. PyYAML |
1310 | +supports standard YAML tags and provides Python-specific tags that |
1311 | +allow to represent an arbitrary Python object. |
1312 | + |
1313 | +PyYAML is applicable for a broad range of tasks from complex |
1314 | +configuration files to object serialization and persistence. |
1315 | + |
1316 | diff --git a/charms/appstream-generator/venv/PyYAML-6.0.dist-info/RECORD b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/RECORD |
1317 | new file mode 100644 |
1318 | index 0000000..7105b9f |
1319 | --- /dev/null |
1320 | +++ b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/RECORD |
1321 | @@ -0,0 +1,43 @@ |
1322 | +PyYAML-6.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 |
1323 | +PyYAML-6.0.dist-info/LICENSE,sha256=jTko-dxEkP1jVwfLiOsmvXZBAqcoKVQwfT5RZ6V36KQ,1101 |
1324 | +PyYAML-6.0.dist-info/METADATA,sha256=QmHx9kGp_0yezQCXYaft4eEFeJ6W4oyFfYwHDLP1kdg,2006 |
1325 | +PyYAML-6.0.dist-info/RECORD,, |
1326 | +PyYAML-6.0.dist-info/WHEEL,sha256=RiwktpmF40OphKd3_aIG01PzIOQlJ7dpBn3cFSc9vak,217 |
1327 | +PyYAML-6.0.dist-info/top_level.txt,sha256=rpj0IVMTisAjh_1vG3Ccf9v5jpCQwAz6cD1IVU5ZdhQ,11 |
1328 | +_yaml/__init__.py,sha256=04Ae_5osxahpJHa3XBZUAf4wi6XX32gR8D6X6p64GEA,1402 |
1329 | +_yaml/__pycache__/__init__.cpython-38.pyc,, |
1330 | +yaml/__init__.py,sha256=NDS7S8XgA72-hY6LRmGzUWTPvzGzjWVrWk-OGA-77AA,12309 |
1331 | +yaml/__pycache__/__init__.cpython-38.pyc,, |
1332 | +yaml/__pycache__/composer.cpython-38.pyc,, |
1333 | +yaml/__pycache__/constructor.cpython-38.pyc,, |
1334 | +yaml/__pycache__/cyaml.cpython-38.pyc,, |
1335 | +yaml/__pycache__/dumper.cpython-38.pyc,, |
1336 | +yaml/__pycache__/emitter.cpython-38.pyc,, |
1337 | +yaml/__pycache__/error.cpython-38.pyc,, |
1338 | +yaml/__pycache__/events.cpython-38.pyc,, |
1339 | +yaml/__pycache__/loader.cpython-38.pyc,, |
1340 | +yaml/__pycache__/nodes.cpython-38.pyc,, |
1341 | +yaml/__pycache__/parser.cpython-38.pyc,, |
1342 | +yaml/__pycache__/reader.cpython-38.pyc,, |
1343 | +yaml/__pycache__/representer.cpython-38.pyc,, |
1344 | +yaml/__pycache__/resolver.cpython-38.pyc,, |
1345 | +yaml/__pycache__/scanner.cpython-38.pyc,, |
1346 | +yaml/__pycache__/serializer.cpython-38.pyc,, |
1347 | +yaml/__pycache__/tokens.cpython-38.pyc,, |
1348 | +yaml/_yaml.cpython-38-x86_64-linux-gnu.so,sha256=lMaKSmQZy3WNZSmmU0Wg5Y5ZAs-HR5vItyGVUIsp8Rg,2847784 |
1349 | +yaml/composer.py,sha256=_Ko30Wr6eDWUeUpauUGT3Lcg9QPBnOPVlTnIMRGJ9FM,4883 |
1350 | +yaml/constructor.py,sha256=kNgkfaeLUkwQYY_Q6Ff1Tz2XVw_pG1xVE9Ak7z-viLA,28639 |
1351 | +yaml/cyaml.py,sha256=6ZrAG9fAYvdVe2FK_w0hmXoG7ZYsoYUwapG8CiC72H0,3851 |
1352 | +yaml/dumper.py,sha256=PLctZlYwZLp7XmeUdwRuv4nYOZ2UBnDIUy8-lKfLF-o,2837 |
1353 | +yaml/emitter.py,sha256=jghtaU7eFwg31bG0B7RZea_29Adi9CKmXq_QjgQpCkQ,43006 |
1354 | +yaml/error.py,sha256=Ah9z-toHJUbE9j-M8YpxgSRM5CgLCcwVzJgLLRF2Fxo,2533 |
1355 | +yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445 |
1356 | +yaml/loader.py,sha256=UVa-zIqmkFSCIYq_PgSGm4NSJttHY2Rf_zQ4_b1fHN0,2061 |
1357 | +yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440 |
1358 | +yaml/parser.py,sha256=ilWp5vvgoHFGzvOZDItFoGjD6D42nhlZrZyjAwa0oJo,25495 |
1359 | +yaml/reader.py,sha256=0dmzirOiDG4Xo41RnuQS7K9rkY3xjHiVasfDMNTqCNw,6794 |
1360 | +yaml/representer.py,sha256=IuWP-cAW9sHKEnS0gCqSa894k1Bg4cgTxaDwIcbRQ-Y,14190 |
1361 | +yaml/resolver.py,sha256=9L-VYfm4mWHxUD1Vg4X7rjDRK_7VZd6b92wzq7Y2IKY,9004 |
1362 | +yaml/scanner.py,sha256=YEM3iLZSaQwXcQRg2l2R4MdT0zGP2F9eHkKGKnHyWQY,51279 |
1363 | +yaml/serializer.py,sha256=ChuFgmhU01hj4xgI8GaKv6vfM2Bujwa9i7d2FAHj7cA,4165 |
1364 | +yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573 |
1365 | diff --git a/charms/appstream-generator/venv/PyYAML-6.0.dist-info/WHEEL b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/WHEEL |
1366 | new file mode 100644 |
1367 | index 0000000..34ce4b8 |
1368 | --- /dev/null |
1369 | +++ b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/WHEEL |
1370 | @@ -0,0 +1,8 @@ |
1371 | +Wheel-Version: 1.0 |
1372 | +Generator: bdist_wheel (0.37.0) |
1373 | +Root-Is-Purelib: false |
1374 | +Tag: cp38-cp38-manylinux_2_5_x86_64 |
1375 | +Tag: cp38-cp38-manylinux1_x86_64 |
1376 | +Tag: cp38-cp38-manylinux_2_12_x86_64 |
1377 | +Tag: cp38-cp38-manylinux2010_x86_64 |
1378 | + |
1379 | diff --git a/charms/appstream-generator/venv/PyYAML-6.0.dist-info/top_level.txt b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/top_level.txt |
1380 | new file mode 100644 |
1381 | index 0000000..e6475e9 |
1382 | --- /dev/null |
1383 | +++ b/charms/appstream-generator/venv/PyYAML-6.0.dist-info/top_level.txt |
1384 | @@ -0,0 +1,2 @@ |
1385 | +_yaml |
1386 | +yaml |
1387 | diff --git a/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/INSTALLER b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/INSTALLER |
1388 | new file mode 100644 |
1389 | index 0000000..a1b589e |
1390 | --- /dev/null |
1391 | +++ b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/INSTALLER |
1392 | @@ -0,0 +1 @@ |
1393 | +pip |
1394 | diff --git a/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/METADATA b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/METADATA |
1395 | new file mode 100644 |
1396 | index 0000000..a5f1fcd |
1397 | --- /dev/null |
1398 | +++ b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/METADATA |
1399 | @@ -0,0 +1,30 @@ |
1400 | +Metadata-Version: 2.1 |
1401 | +Name: Tempita |
1402 | +Version: 0.5.2 |
1403 | +Summary: A very small text templating language |
1404 | +Home-page: http://pythonpaste.org/tempita/ |
1405 | +Author: Ian Bicking |
1406 | +Author-email: ianb@colorstudy.com |
1407 | +License: MIT |
1408 | +Keywords: templating template language html |
1409 | +Platform: UNKNOWN |
1410 | +Classifier: Development Status :: 4 - Beta |
1411 | +Classifier: Intended Audience :: Developers |
1412 | +Classifier: License :: OSI Approved :: MIT License |
1413 | +Classifier: Topic :: Text Processing |
1414 | +Classifier: Programming Language :: Python :: 2 |
1415 | +Classifier: Programming Language :: Python :: 3 |
1416 | + |
1417 | +Tempita is a small templating language for text substitution. |
1418 | + |
1419 | +This isn't meant to be the Next Big Thing in templating; it's just a |
1420 | +handy little templating language for when your project outgrows |
1421 | +``string.Template`` or ``%`` substitution. It's small, it embeds |
1422 | +Python in strings, and it doesn't do much else. |
1423 | + |
1424 | +You can read about the `language |
1425 | +<http://pythonpaste.org/tempita/#the-language>`_, the `interface |
1426 | +<http://pythonpaste.org/tempita/#the-interface>`_, and there's nothing |
1427 | +more to learn about it. |
1428 | + |
1429 | + |
1430 | diff --git a/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/RECORD b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/RECORD |
1431 | new file mode 100644 |
1432 | index 0000000..f74b6b1 |
1433 | --- /dev/null |
1434 | +++ b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/RECORD |
1435 | @@ -0,0 +1,14 @@ |
1436 | +Tempita-0.5.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 |
1437 | +Tempita-0.5.2.dist-info/METADATA,sha256=WDCnE3v--BhabjMdVq9G-O_kmuimR1grwKxXtGdMibI,1048 |
1438 | +Tempita-0.5.2.dist-info/RECORD,, |
1439 | +Tempita-0.5.2.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92 |
1440 | +Tempita-0.5.2.dist-info/top_level.txt,sha256=2y9rvt_84XtP01ieixzzLnKmE9uWXFZteDjBnAXpDow,8 |
1441 | +Tempita-0.5.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 |
1442 | +tempita/__init__.py,sha256=MOpudct6XWwEKdFsS-t-QBCkrhJzaRf8UYQO2X58HLs,39822 |
1443 | +tempita/__main__.py,sha256=odLX23WPEN1ld-BWsAUHhT-npHpedjL9d_B0lijyNwk,49 |
1444 | +tempita/__pycache__/__init__.cpython-38.pyc,, |
1445 | +tempita/__pycache__/__main__.cpython-38.pyc,, |
1446 | +tempita/__pycache__/_looper.cpython-38.pyc,, |
1447 | +tempita/__pycache__/compat3.cpython-38.pyc,, |
1448 | +tempita/_looper.py,sha256=-CLh64iZ6c1czHxchvibTyOyMm7_mS81oleO6FBwcMg,4164 |
1449 | +tempita/compat3.py,sha256=y4HPrDVYmij84_bHi3Pk1A02SvvTmm98eodpWgxzH20,838 |
1450 | diff --git a/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/WHEEL b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/WHEEL |
1451 | new file mode 100644 |
1452 | index 0000000..5bad85f |
1453 | --- /dev/null |
1454 | +++ b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/WHEEL |
1455 | @@ -0,0 +1,5 @@ |
1456 | +Wheel-Version: 1.0 |
1457 | +Generator: bdist_wheel (0.37.0) |
1458 | +Root-Is-Purelib: true |
1459 | +Tag: py3-none-any |
1460 | + |
1461 | diff --git a/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/top_level.txt b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/top_level.txt |
1462 | new file mode 100644 |
1463 | index 0000000..eddfc48 |
1464 | --- /dev/null |
1465 | +++ b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/top_level.txt |
1466 | @@ -0,0 +1 @@ |
1467 | +tempita |
1468 | diff --git a/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/zip-safe b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/zip-safe |
1469 | new file mode 100644 |
1470 | index 0000000..8b13789 |
1471 | --- /dev/null |
1472 | +++ b/charms/appstream-generator/venv/Tempita-0.5.2.dist-info/zip-safe |
1473 | @@ -0,0 +1 @@ |
1474 | + |
1475 | diff --git a/charms/appstream-generator/venv/__pycache__/six.cpython-38.pyc b/charms/appstream-generator/venv/__pycache__/six.cpython-38.pyc |
1476 | new file mode 100644 |
1477 | index 0000000..07e38cc |
1478 | Binary files /dev/null and b/charms/appstream-generator/venv/__pycache__/six.cpython-38.pyc differ |
1479 | diff --git a/charms/appstream-generator/venv/_yaml/__init__.py b/charms/appstream-generator/venv/_yaml/__init__.py |
1480 | new file mode 100644 |
1481 | index 0000000..7baa8c4 |
1482 | --- /dev/null |
1483 | +++ b/charms/appstream-generator/venv/_yaml/__init__.py |
1484 | @@ -0,0 +1,33 @@ |
1485 | +# This is a stub package designed to roughly emulate the _yaml |
1486 | +# extension module, which previously existed as a standalone module |
1487 | +# and has been moved into the `yaml` package namespace. |
1488 | +# It does not perfectly mimic its old counterpart, but should get |
1489 | +# close enough for anyone who's relying on it even when they shouldn't. |
1490 | +import yaml |
1491 | + |
1492 | +# in some circumstances, the yaml module we imoprted may be from a different version, so we need |
1493 | +# to tread carefully when poking at it here (it may not have the attributes we expect) |
1494 | +if not getattr(yaml, '__with_libyaml__', False): |
1495 | + from sys import version_info |
1496 | + |
1497 | + exc = ModuleNotFoundError if version_info >= (3, 6) else ImportError |
1498 | + raise exc("No module named '_yaml'") |
1499 | +else: |
1500 | + from yaml._yaml import * |
1501 | + import warnings |
1502 | + warnings.warn( |
1503 | + 'The _yaml extension module is now located at yaml._yaml' |
1504 | + ' and its location is subject to change. To use the' |
1505 | + ' LibYAML-based parser and emitter, import from `yaml`:' |
1506 | + ' `from yaml import CLoader as Loader, CDumper as Dumper`.', |
1507 | + DeprecationWarning |
1508 | + ) |
1509 | + del warnings |
1510 | + # Don't `del yaml` here because yaml is actually an existing |
1511 | + # namespace member of _yaml. |
1512 | + |
1513 | +__name__ = '_yaml' |
1514 | +# If the module is top-level (i.e. not a part of any specific package) |
1515 | +# then the attribute should be set to ''. |
1516 | +# https://docs.python.org/3.8/library/types.html |
1517 | +__package__ = '' |
1518 | diff --git a/charms/appstream-generator/venv/_yaml/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/_yaml/__pycache__/__init__.cpython-38.pyc |
1519 | new file mode 100644 |
1520 | index 0000000..4ea8a2e |
1521 | Binary files /dev/null and b/charms/appstream-generator/venv/_yaml/__pycache__/__init__.cpython-38.pyc differ |
1522 | diff --git a/charms/appstream-generator/venv/bin/charmsupport b/charms/appstream-generator/venv/bin/charmsupport |
1523 | new file mode 100755 |
1524 | index 0000000..15759e2 |
1525 | --- /dev/null |
1526 | +++ b/charms/appstream-generator/venv/bin/charmsupport |
1527 | @@ -0,0 +1,31 @@ |
1528 | +#!/usr/bin/python3 |
1529 | + |
1530 | +import argparse |
1531 | +from charmhelpers.contrib.charmsupport import execd |
1532 | + |
1533 | + |
1534 | +def run_execd(args): |
1535 | + execd.execd_run(args.module, args.dir, die_on_error=True) |
1536 | + |
1537 | + |
1538 | +def parse_args(): |
1539 | + parser = argparse.ArgumentParser(description='Perform common charm tasks') |
1540 | + subparsers = parser.add_subparsers(help='Commands') |
1541 | + |
1542 | + execd_parser = subparsers.add_parser('execd', |
1543 | + help='Execute a directory of commands') |
1544 | + execd_parser.add_argument('--module', default='charm-pre-install', |
1545 | + help='module to run (default: charm-pre-install)') |
1546 | + execd_parser.add_argument('--dir', |
1547 | + help="Override the exec.d directory path") |
1548 | + execd_parser.set_defaults(func=run_execd) |
1549 | + |
1550 | + return parser.parse_args() |
1551 | + |
1552 | + |
1553 | +def main(): |
1554 | + arguments = parse_args() |
1555 | + arguments.func(arguments) |
1556 | + |
1557 | +if __name__ == '__main__': |
1558 | + exit(main()) |
1559 | diff --git a/charms/appstream-generator/venv/bin/chlp b/charms/appstream-generator/venv/bin/chlp |
1560 | new file mode 100755 |
1561 | index 0000000..6bf2d2b |
1562 | --- /dev/null |
1563 | +++ b/charms/appstream-generator/venv/bin/chlp |
1564 | @@ -0,0 +1,8 @@ |
1565 | +#!/usr/bin/python3 |
1566 | + |
1567 | +from charmhelpers.cli import cmdline |
1568 | +from charmhelpers.cli.commands import * |
1569 | + |
1570 | + |
1571 | +if __name__ == '__main__': |
1572 | + cmdline.run() |
1573 | diff --git a/charms/appstream-generator/venv/bin/netaddr b/charms/appstream-generator/venv/bin/netaddr |
1574 | new file mode 100755 |
1575 | index 0000000..f2faba5 |
1576 | --- /dev/null |
1577 | +++ b/charms/appstream-generator/venv/bin/netaddr |
1578 | @@ -0,0 +1,8 @@ |
1579 | +#!/usr/bin/python3 |
1580 | +# -*- coding: utf-8 -*- |
1581 | +import re |
1582 | +import sys |
1583 | +from netaddr.cli import main |
1584 | +if __name__ == '__main__': |
1585 | + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) |
1586 | + sys.exit(main()) |
1587 | diff --git a/charms/appstream-generator/venv/bin/pbr b/charms/appstream-generator/venv/bin/pbr |
1588 | new file mode 100755 |
1589 | index 0000000..730fb39 |
1590 | --- /dev/null |
1591 | +++ b/charms/appstream-generator/venv/bin/pbr |
1592 | @@ -0,0 +1,8 @@ |
1593 | +#!/usr/bin/python3 |
1594 | +# -*- coding: utf-8 -*- |
1595 | +import re |
1596 | +import sys |
1597 | +from pbr.cmd.main import main |
1598 | +if __name__ == '__main__': |
1599 | + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) |
1600 | + sys.exit(main()) |
1601 | diff --git a/charms/appstream-generator/venv/bin/salt-call b/charms/appstream-generator/venv/bin/salt-call |
1602 | new file mode 100755 |
1603 | index 0000000..d641b0a |
1604 | --- /dev/null |
1605 | +++ b/charms/appstream-generator/venv/bin/salt-call |
1606 | @@ -0,0 +1,11 @@ |
1607 | +#!/usr/bin/python3 |
1608 | +''' |
1609 | +Directly call a salt command in the modules, does not require a running salt |
1610 | +minion to run. |
1611 | +''' |
1612 | + |
1613 | +from salt.scripts import salt_call |
1614 | + |
1615 | + |
1616 | +if __name__ == '__main__': |
1617 | + salt_call() |
1618 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/AUTHORS b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/AUTHORS |
1619 | new file mode 100644 |
1620 | index 0000000..41e552d |
1621 | --- /dev/null |
1622 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/AUTHORS |
1623 | @@ -0,0 +1,222 @@ |
1624 | +Adam Collard <adam.collard@canonical.com> |
1625 | +Adam Dyess <adam.dyess@canonical.com> |
1626 | +Adam Dyess <adyess@gmail.com> |
1627 | +Adam Gandelman <adamg@canonical.com> |
1628 | +Adam Gandelman <adamg@ubuntu.com> |
1629 | +Adam Israel <adam.israel@gmail.com> |
1630 | +Alex Kavanagh <567675+ajkavanagh@users.noreply.github.com> |
1631 | +Alex Kavanagh <ajkavanagh@users.noreply.github.com> |
1632 | +Alex Kavanagh <alex.kavanagh@canonical.com> |
1633 | +Alex Kavanagh <alex@ajkavanagh.co.uk> |
1634 | +Alexandros Soumplis <a.soumplis@gmail.com> |
1635 | +Alvaro UrÃa <alvaro.uria@canonical.com> |
1636 | +Andreas Hasenack <andreas@canonical.com> |
1637 | +Andres Rodriguez <andreserl@ubuntu.com> |
1638 | +Andrew McLeod <andrew.mcleod@canonical.com> |
1639 | +Andrew Wilkins <andrew.wilkins@canonical.com> |
1640 | +Ante Karamatic <ante.karamatic@canonical.com> |
1641 | +Ante Karamatic <ivoks@ubuntu.com> |
1642 | +Anton Skriptsov anton.skriptsov@nexenta.com <> |
1643 | +Antoni Segura Puimedon <toni@midokura.com> |
1644 | +Arif Ali <arif-ali@users.noreply.github.com> |
1645 | +Aurelien Lourot <aurelien.lourot@canonical.com> |
1646 | +Aurelien Lourot <aurelien.lourot@gmail.com> |
1647 | +Barry Price <barryprice@users.noreply.github.com> |
1648 | +Beaujolais ! <axino@canonical.com> |
1649 | +Ben Kaehne <ben.kaehne@canonical.com> |
1650 | +Benjamin Saller <benjamin.saller@canonical.com> |
1651 | +Bilal Baqar <bbaqar@plumgrid.com> |
1652 | +Billy Olsen <billy.olsen@canonical.com> |
1653 | +Billy Olsen <wolsen@users.noreply.github.com> |
1654 | +Bjorn Tillenius <bjorn@tillenius.me> |
1655 | +Brad Marshall <brad.marshall@canonical.com> |
1656 | +Brett <19863984+brettmilford@users.noreply.github.com> |
1657 | +Brett Milford <brettmilford@gmail.com> |
1658 | +Brian Murray <brian@canonical.com> |
1659 | +Brian Murray <brian@murraytwins.com> |
1660 | +Brian Murray <brian@ubuntu.com> |
1661 | +Casey Marshall <casey.marshall@canonical.com> |
1662 | +Chad Smith <chad.smith@canonical.com> |
1663 | +Charles Butler <charles.butler@canonical.com> |
1664 | +Charles Butler <chuck@dasroot.net> |
1665 | +Chris Holcombe <chris.holcombe@canonical.com> |
1666 | +Chris J Arges <chris.j.arges@canonical.com> |
1667 | +Chris Johnston <chrisjohnston@ubuntu.com> |
1668 | +Chris Johnston <cjohnston1158@users.noreply.github.com> |
1669 | +Chris MacNaughton <chmacnaughton@gmail.com> |
1670 | +Chris MacNaughton <chris.macnaughton@canonical.com> |
1671 | +Chris MacNaughton <chris@centaurisolutions.nl> |
1672 | +Chris Sanders <sanders.chris@gmail.com> |
1673 | +Chris Stratford <chris.stratford@canonical.com> |
1674 | +Christopher Glass <christopher.glass@canonical.com> |
1675 | +Chuck Short <zulcss@ubuntu.com> |
1676 | +Colin Watson <cjwatson@ubuntu.com> |
1677 | +Corey Bryant <corey.bryant@canonical.com> |
1678 | +Cory Benfield <cory.benfield@metaswitch.com> |
1679 | +Cory Johns <cory.johns@canonical.com> |
1680 | +Cory Johns <johnsca@gmail.com> |
1681 | +Craige McWhirter <craige@mcwhirter.io> |
1682 | +Dan Ryan <dan@danryan.co> |
1683 | +Daniel Watkins <daniel.watkins@canonical.com> |
1684 | +Dave Lawson <dave.lawson@canonical.com> |
1685 | +David Ames <david.ames@canonical.com> |
1686 | +David Ames <david@davam.net> |
1687 | +David Britton <david.britton@canonical.com> |
1688 | +David Della Vecchia <ddv@canonical.com> |
1689 | +Denis Buliga <dbuliga@cloudbasesolutions.com> |
1690 | +Diko Parvanov <42830406+dparv@users.noreply.github.com> |
1691 | +Dmitrii Shcherbakov <dshcherb@users.noreply.github.com> |
1692 | +Domas Monkus <domas.monkus@canonical.com> |
1693 | +Drew Freiberger <drew.freiberger@canonical.com> |
1694 | +Duyle Campos <duyleruan@hotmail.com> |
1695 | +Edward Hope-Morley <edward.hope-morley@canonical.com> |
1696 | +Edward Hope-Morley <opentastic@gmail.com> |
1697 | +Erlon R. Cruz <erlon@canonical.com> |
1698 | +Evan Dandrea <evan.dandrea@canonical.com> |
1699 | +Felipe Reyes <felipe.reyes@canonical.com> |
1700 | +Felipe Reyes <freyes@tty.cl> |
1701 | +Francis Ginther <francis.ginther@canonical.com> |
1702 | +Free Ekanayaka <free.ekanayaka@canonical.com> |
1703 | +Frode Nordahl <frode.nordahl@canonical.com> |
1704 | +Frode Nordahl <frode.nordahl@gmail.com> |
1705 | +Gabor Meszaros gabor.meszaros@canonical.com <> |
1706 | +Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com> |
1707 | +Gabriel Angelo Sgarbi Cocenza <gabrielcocenza@gmail.com> |
1708 | +Gareth Woolridge <gareth.woolridge@canonical.com> |
1709 | +Geoffrey J. Teale <geoffrey.teale@canonical.com> |
1710 | +George Kraft <cynerva@gmail.com> |
1711 | +Guo Qiao (Joe) <guoqiao@gmail.com> |
1712 | +Haw Loeung (hloeung) <haw.loeung@canonical.com> |
1713 | +Haw Loeung <h.loeung+github@unixque.com> |
1714 | +Haw Loeung <haw.loeung@canonical.com> |
1715 | +Hemanth Nakkina <hemanth.nakkina@canonical.com> |
1716 | +Hui Xiang <hui.xiang@canonical.com> |
1717 | +Ian Booth <ian.booth@canonical.com> |
1718 | +Ionut Balutoiu <ibalutoiu@cloudbasesolutions.com> |
1719 | +Jacek Nykis <jacek.nykis@canonical.com> |
1720 | +James Beedy <jamesbeedy@gmail.com> |
1721 | +James Beedy <jbeedy@virt-test0> |
1722 | +James Page <james.page@canonical.com> |
1723 | +James Page <james.page@ubuntu.com> |
1724 | +James Troup <james.troup@canonical.com> |
1725 | +Jason Hobbs <jason.hobbs@gmail.com> |
1726 | +Jian Wen <jian.wen@canonical.com> |
1727 | +Joe Borg <cyborg101010@gmail.com> |
1728 | +Joe Borg <joseph.borg@canonical.com> |
1729 | +Jonathan Herlin <Jonte@jherlin.se> |
1730 | +Jorge Niedbalski <jorge.niedbalski@canonical.com> |
1731 | +Jorge Niedbalski R <jorge.niedbalski@canonical.com> |
1732 | +Joseph Borg <joseph.borg@canonical.com> |
1733 | +Joshua Powers <mrpowersj@gmail.com> |
1734 | +Juan L. Negron <juan@ubuntu.com> |
1735 | +JuanJo Ciarlante <jjo@canonical.com> |
1736 | +Kapil Thangavelu <kapil@canonical.com> |
1737 | +Kevin W Monroe <kevin.monroe@canonical.com> |
1738 | +Kit Randel <kit.randel@canonical.com> |
1739 | +Laurent Sesquès <sajoupa@users.noreply.github.com> |
1740 | +Liam Young <liam.young@canonical.com> |
1741 | +Liam Young <liam@landv.org.uk> |
1742 | +Liam young <liam.young@canonical.com> |
1743 | +Liang Chen liang.chen@canonical.com <> |
1744 | +Lihui <lihuiguo@gmail.com> |
1745 | +Linda Guo <linda.guo@canonical.com> |
1746 | +Marco CEppi <marco@ceppi.net> |
1747 | +Marco Ceppi <marco@T430> |
1748 | +Marco Ceppi <marco@ceppi.net> |
1749 | +Mario Splivalo <mario.splivalo@canonical.com> |
1750 | +Marius Oprin <moprin@cloudbasesolutions.com> |
1751 | +Martin Hilton <martin.hilton@canonical.com> |
1752 | +Matt Bruzek <matthew.bruzek@canonical.com> |
1753 | +Matt Bruzek matthew.bruzek@canonical.com <> |
1754 | +Matt Rae <matt.rae@canonical.com> |
1755 | +Matthew Bruzek <matthew.bruzek@canonical.com> |
1756 | +Matthew Wedgwood <matthew.wedgwood@canonical.com> |
1757 | +Matúš Košút <matuskosut@users.noreply.github.com> |
1758 | +Merlijn Sebrechts <merlijn.sebrechts@gmail.com> |
1759 | +Michael Nelson <michael.nelson@canonical.com> |
1760 | +Michael Skalka <michael.skalka@canonical.com> |
1761 | +Michał Sawicz <michal.sawicz@canonical.com> |
1762 | +Narinder Gupta <narinder.gupta@canonical.com> |
1763 | +Nathan Osman <nathan@quickmediasolutions.com> |
1764 | +Nick Moffitt <nick.moffitt@canonical.com> |
1765 | +Nicolas Bock <nicolasbock@gmail.com> |
1766 | +Nicolas Pochet <npochet@automate-solutions.com> |
1767 | +Nikolay Nikolaev <nicknickolaev@gmail.com> |
1768 | +Nikolay Nikolaev <nikolay.nikolaev@canonical.com> |
1769 | +Nikolay Vinogradov <32940265+nikolayvinogradov@users.noreply.github.com> |
1770 | +Nobuto Murata <nobuto.murata@canonical.com> |
1771 | +Oprin Marius <moprin@cloudbasesolutions.com> |
1772 | +Paolo de Rosa <paolo.de.rosa@canonical.com> |
1773 | +Patrick Hetu <patrick.hetu@gmail.com> |
1774 | +Paul Collins <paul.collins@canonical.com> |
1775 | +Paul Gear <paul.gear@canonical.com> |
1776 | +Pedro Guimaraes <pedro.guimaraes@canonical.com> |
1777 | +Pete Vander Giessen <petevg@gmail.com> |
1778 | +Peter Sabaini <peter.sabaini@canonical.com> |
1779 | +Peter Sabaini <peter@sabaini.at> |
1780 | +Ponnuvel Palaniyappan <pponnuvel@gmail.com> |
1781 | +Przemysław Lal <przemeklal@gmail.com> |
1782 | +Przemysław Lal <przemyslaw.lal@canonical.com> |
1783 | +Rick Harding <rharding@mitechie.com> |
1784 | +Robert Jennings <robert.jennings@canonical.com> |
1785 | +Rodrigo Barbieri <rodrigo.barbieri2010@gmail.com> |
1786 | +Ryan Beisner <ryan-beisner@users.noreply.github.com> |
1787 | +Ryan Beisner <ryan.beisner@canonical.com> |
1788 | +Ryan Harper <ryan.harper@ubuntu.com> |
1789 | +Sahid Orentino Ferdjaoui <sahid.ferdjaoui@libremel.fr> |
1790 | +Sandor Zeestraten <sandor.zeestraten@ntnu.no> |
1791 | +Scott Moser <smoser@ubuntu.com> |
1792 | +Seyeong Kim <seyeong.kim@canonical.com> |
1793 | +Seyeong Kim <xtrusia@gmail.com> |
1794 | +Shiva Prasad Rao <shivrao@cisco.com> |
1795 | +Simon Davy <bloodearnest@gmail.com> |
1796 | +Simon Kollberg <simon@asfalt> |
1797 | +Simon Poirier <simon.poirier@canonical.com> |
1798 | +Stamatis Katsaounis <katsaouniss@gmail.com> |
1799 | +Stephan <7194553+SPFZ@users.noreply.github.com> |
1800 | +Stuart Bishop <stuart.bishop@canonical.com> |
1801 | +Stuart Bishop <stuart@stuartbishop.net> |
1802 | +Stuart Bishop <stub@canonical.com> |
1803 | +Stub <stuart.bishop@canonical.com> |
1804 | +Stub <stuart@stuartbishop.net> |
1805 | +Subbarayudu Mukkamala <smukkamala@nuagenetworks.net> |
1806 | +Sunny Verma <sunny.verma@nuagenetworks.net> |
1807 | +Sunny Verma <sunnyverma1992@gmail.com> |
1808 | +Tiago Pasqualini <tiago.pasqualini@gmail.com> |
1809 | +Tim Kuhlman <timothy.kuhlman@canonical.com> |
1810 | +Tim McNamara <code@timmcnamara.co.nz> |
1811 | +Tim McNamara <tim.mcnamara@canonical.com> |
1812 | +Tim Van Steenburgh <tim.van.steenburgh@canonical.com> |
1813 | +Tim Van Steenburgh <tvansteenburgh@gmail.com> |
1814 | +Tom Haddon <tom.haddon@canonical.com> |
1815 | +Trent Lloyd <trent.lloyd@canonical.com> |
1816 | +Tytus Kurek <tkurek@itsteer.com> |
1817 | +Tytus Kurek <tytus.kurek@canonical.com> |
1818 | +Ubuntu <ubuntu@gabrielcocenza-bastion.project.serverstack> |
1819 | +Ubuntu <ubuntu@localhost.localdomain> |
1820 | +Vladimir Grevtsev <vlgrevtsev@gmail.com> |
1821 | +Xtrusia <xtrusia@xtrusia-desktop> |
1822 | +Yaguang Tang <yaguang.tang@canonical.com> |
1823 | +Yang Kelvin <kelvin.liu@canonical.com> |
1824 | +Zhang Hua <joshua.zhang@canonical.com> |
1825 | +afrikha <aymen.frikha@canonical.com> |
1826 | +amulet@dummy-user.tld <> |
1827 | +andrew.glen-young@canonical.com <> |
1828 | +axino <axino@canonical.com> |
1829 | +billy.olsen@canonical.com <> |
1830 | +charles butler <Charles.butler@ubuntu.com> |
1831 | +chris.macnaughton@canonical.com <> |
1832 | +coreycb <corey.bryant@canonical.com> |
1833 | +dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
1834 | +evilnick <> |
1835 | +hemanthnakkina <mail2hemanth.n@gmail.com> |
1836 | +joshua.zhang@canonical.com <> |
1837 | +jrwren@xmtp.net <> |
1838 | +mattyw <lp@mattyw.net> |
1839 | +michael.skalka@canonical.com <> |
1840 | +mkalcok <69471063+mkalcok@users.noreply.github.com> |
1841 | +shane.peters@canonical.com <> |
1842 | +stub42 <stuart@stuartbishop.net> |
1843 | +vincenzo di somma <vincenzo.di.somma@canonical.com> |
1844 | +xavpaice <xavpaice@users.noreply.github.com> |
1845 | +yolanda.robla@canonical.com <> |
1846 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/INSTALLER b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/INSTALLER |
1847 | new file mode 100644 |
1848 | index 0000000..a1b589e |
1849 | --- /dev/null |
1850 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/INSTALLER |
1851 | @@ -0,0 +1 @@ |
1852 | +pip |
1853 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/LICENSE b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/LICENSE |
1854 | new file mode 100644 |
1855 | index 0000000..d645695 |
1856 | --- /dev/null |
1857 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/LICENSE |
1858 | @@ -0,0 +1,202 @@ |
1859 | + |
1860 | + Apache License |
1861 | + Version 2.0, January 2004 |
1862 | + http://www.apache.org/licenses/ |
1863 | + |
1864 | + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
1865 | + |
1866 | + 1. Definitions. |
1867 | + |
1868 | + "License" shall mean the terms and conditions for use, reproduction, |
1869 | + and distribution as defined by Sections 1 through 9 of this document. |
1870 | + |
1871 | + "Licensor" shall mean the copyright owner or entity authorized by |
1872 | + the copyright owner that is granting the License. |
1873 | + |
1874 | + "Legal Entity" shall mean the union of the acting entity and all |
1875 | + other entities that control, are controlled by, or are under common |
1876 | + control with that entity. For the purposes of this definition, |
1877 | + "control" means (i) the power, direct or indirect, to cause the |
1878 | + direction or management of such entity, whether by contract or |
1879 | + otherwise, or (ii) ownership of fifty percent (50%) or more of the |
1880 | + outstanding shares, or (iii) beneficial ownership of such entity. |
1881 | + |
1882 | + "You" (or "Your") shall mean an individual or Legal Entity |
1883 | + exercising permissions granted by this License. |
1884 | + |
1885 | + "Source" form shall mean the preferred form for making modifications, |
1886 | + including but not limited to software source code, documentation |
1887 | + source, and configuration files. |
1888 | + |
1889 | + "Object" form shall mean any form resulting from mechanical |
1890 | + transformation or translation of a Source form, including but |
1891 | + not limited to compiled object code, generated documentation, |
1892 | + and conversions to other media types. |
1893 | + |
1894 | + "Work" shall mean the work of authorship, whether in Source or |
1895 | + Object form, made available under the License, as indicated by a |
1896 | + copyright notice that is included in or attached to the work |
1897 | + (an example is provided in the Appendix below). |
1898 | + |
1899 | + "Derivative Works" shall mean any work, whether in Source or Object |
1900 | + form, that is based on (or derived from) the Work and for which the |
1901 | + editorial revisions, annotations, elaborations, or other modifications |
1902 | + represent, as a whole, an original work of authorship. For the purposes |
1903 | + of this License, Derivative Works shall not include works that remain |
1904 | + separable from, or merely link (or bind by name) to the interfaces of, |
1905 | + the Work and Derivative Works thereof. |
1906 | + |
1907 | + "Contribution" shall mean any work of authorship, including |
1908 | + the original version of the Work and any modifications or additions |
1909 | + to that Work or Derivative Works thereof, that is intentionally |
1910 | + submitted to Licensor for inclusion in the Work by the copyright owner |
1911 | + or by an individual or Legal Entity authorized to submit on behalf of |
1912 | + the copyright owner. For the purposes of this definition, "submitted" |
1913 | + means any form of electronic, verbal, or written communication sent |
1914 | + to the Licensor or its representatives, including but not limited to |
1915 | + communication on electronic mailing lists, source code control systems, |
1916 | + and issue tracking systems that are managed by, or on behalf of, the |
1917 | + Licensor for the purpose of discussing and improving the Work, but |
1918 | + excluding communication that is conspicuously marked or otherwise |
1919 | + designated in writing by the copyright owner as "Not a Contribution." |
1920 | + |
1921 | + "Contributor" shall mean Licensor and any individual or Legal Entity |
1922 | + on behalf of whom a Contribution has been received by Licensor and |
1923 | + subsequently incorporated within the Work. |
1924 | + |
1925 | + 2. Grant of Copyright License. Subject to the terms and conditions of |
1926 | + this License, each Contributor hereby grants to You a perpetual, |
1927 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
1928 | + copyright license to reproduce, prepare Derivative Works of, |
1929 | + publicly display, publicly perform, sublicense, and distribute the |
1930 | + Work and such Derivative Works in Source or Object form. |
1931 | + |
1932 | + 3. Grant of Patent License. Subject to the terms and conditions of |
1933 | + this License, each Contributor hereby grants to You a perpetual, |
1934 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
1935 | + (except as stated in this section) patent license to make, have made, |
1936 | + use, offer to sell, sell, import, and otherwise transfer the Work, |
1937 | + where such license applies only to those patent claims licensable |
1938 | + by such Contributor that are necessarily infringed by their |
1939 | + Contribution(s) alone or by combination of their Contribution(s) |
1940 | + with the Work to which such Contribution(s) was submitted. If You |
1941 | + institute patent litigation against any entity (including a |
1942 | + cross-claim or counterclaim in a lawsuit) alleging that the Work |
1943 | + or a Contribution incorporated within the Work constitutes direct |
1944 | + or contributory patent infringement, then any patent licenses |
1945 | + granted to You under this License for that Work shall terminate |
1946 | + as of the date such litigation is filed. |
1947 | + |
1948 | + 4. Redistribution. You may reproduce and distribute copies of the |
1949 | + Work or Derivative Works thereof in any medium, with or without |
1950 | + modifications, and in Source or Object form, provided that You |
1951 | + meet the following conditions: |
1952 | + |
1953 | + (a) You must give any other recipients of the Work or |
1954 | + Derivative Works a copy of this License; and |
1955 | + |
1956 | + (b) You must cause any modified files to carry prominent notices |
1957 | + stating that You changed the files; and |
1958 | + |
1959 | + (c) You must retain, in the Source form of any Derivative Works |
1960 | + that You distribute, all copyright, patent, trademark, and |
1961 | + attribution notices from the Source form of the Work, |
1962 | + excluding those notices that do not pertain to any part of |
1963 | + the Derivative Works; and |
1964 | + |
1965 | + (d) If the Work includes a "NOTICE" text file as part of its |
1966 | + distribution, then any Derivative Works that You distribute must |
1967 | + include a readable copy of the attribution notices contained |
1968 | + within such NOTICE file, excluding those notices that do not |
1969 | + pertain to any part of the Derivative Works, in at least one |
1970 | + of the following places: within a NOTICE text file distributed |
1971 | + as part of the Derivative Works; within the Source form or |
1972 | + documentation, if provided along with the Derivative Works; or, |
1973 | + within a display generated by the Derivative Works, if and |
1974 | + wherever such third-party notices normally appear. The contents |
1975 | + of the NOTICE file are for informational purposes only and |
1976 | + do not modify the License. You may add Your own attribution |
1977 | + notices within Derivative Works that You distribute, alongside |
1978 | + or as an addendum to the NOTICE text from the Work, provided |
1979 | + that such additional attribution notices cannot be construed |
1980 | + as modifying the License. |
1981 | + |
1982 | + You may add Your own copyright statement to Your modifications and |
1983 | + may provide additional or different license terms and conditions |
1984 | + for use, reproduction, or distribution of Your modifications, or |
1985 | + for any such Derivative Works as a whole, provided Your use, |
1986 | + reproduction, and distribution of the Work otherwise complies with |
1987 | + the conditions stated in this License. |
1988 | + |
1989 | + 5. Submission of Contributions. Unless You explicitly state otherwise, |
1990 | + any Contribution intentionally submitted for inclusion in the Work |
1991 | + by You to the Licensor shall be under the terms and conditions of |
1992 | + this License, without any additional terms or conditions. |
1993 | + Notwithstanding the above, nothing herein shall supersede or modify |
1994 | + the terms of any separate license agreement you may have executed |
1995 | + with Licensor regarding such Contributions. |
1996 | + |
1997 | + 6. Trademarks. This License does not grant permission to use the trade |
1998 | + names, trademarks, service marks, or product names of the Licensor, |
1999 | + except as required for reasonable and customary use in describing the |
2000 | + origin of the Work and reproducing the content of the NOTICE file. |
2001 | + |
2002 | + 7. Disclaimer of Warranty. Unless required by applicable law or |
2003 | + agreed to in writing, Licensor provides the Work (and each |
2004 | + Contributor provides its Contributions) on an "AS IS" BASIS, |
2005 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
2006 | + implied, including, without limitation, any warranties or conditions |
2007 | + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
2008 | + PARTICULAR PURPOSE. You are solely responsible for determining the |
2009 | + appropriateness of using or redistributing the Work and assume any |
2010 | + risks associated with Your exercise of permissions under this License. |
2011 | + |
2012 | + 8. Limitation of Liability. In no event and under no legal theory, |
2013 | + whether in tort (including negligence), contract, or otherwise, |
2014 | + unless required by applicable law (such as deliberate and grossly |
2015 | + negligent acts) or agreed to in writing, shall any Contributor be |
2016 | + liable to You for damages, including any direct, indirect, special, |
2017 | + incidental, or consequential damages of any character arising as a |
2018 | + result of this License or out of the use or inability to use the |
2019 | + Work (including but not limited to damages for loss of goodwill, |
2020 | + work stoppage, computer failure or malfunction, or any and all |
2021 | + other commercial damages or losses), even if such Contributor |
2022 | + has been advised of the possibility of such damages. |
2023 | + |
2024 | + 9. Accepting Warranty or Additional Liability. While redistributing |
2025 | + the Work or Derivative Works thereof, You may choose to offer, |
2026 | + and charge a fee for, acceptance of support, warranty, indemnity, |
2027 | + or other liability obligations and/or rights consistent with this |
2028 | + License. However, in accepting such obligations, You may act only |
2029 | + on Your own behalf and on Your sole responsibility, not on behalf |
2030 | + of any other Contributor, and only if You agree to indemnify, |
2031 | + defend, and hold each Contributor harmless for any liability |
2032 | + incurred by, or claims asserted against, such Contributor by reason |
2033 | + of your accepting any such warranty or additional liability. |
2034 | + |
2035 | + END OF TERMS AND CONDITIONS |
2036 | + |
2037 | + APPENDIX: How to apply the Apache License to your work. |
2038 | + |
2039 | + To apply the Apache License to your work, attach the following |
2040 | + boilerplate notice, with the fields enclosed by brackets "[]" |
2041 | + replaced with your own identifying information. (Don't include |
2042 | + the brackets!) The text should be enclosed in the appropriate |
2043 | + comment syntax for the file format. We also recommend that a |
2044 | + file or class name and description of purpose be included on the |
2045 | + same "printed page" as the copyright notice for easier |
2046 | + identification within third-party archives. |
2047 | + |
2048 | + Copyright [yyyy] [name of copyright owner] |
2049 | + |
2050 | + Licensed under the Apache License, Version 2.0 (the "License"); |
2051 | + you may not use this file except in compliance with the License. |
2052 | + You may obtain a copy of the License at |
2053 | + |
2054 | + http://www.apache.org/licenses/LICENSE-2.0 |
2055 | + |
2056 | + Unless required by applicable law or agreed to in writing, software |
2057 | + distributed under the License is distributed on an "AS IS" BASIS, |
2058 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2059 | + See the License for the specific language governing permissions and |
2060 | + limitations under the License. |
2061 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/METADATA b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/METADATA |
2062 | new file mode 100644 |
2063 | index 0000000..9e4fc06 |
2064 | --- /dev/null |
2065 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/METADATA |
2066 | @@ -0,0 +1,82 @@ |
2067 | +Metadata-Version: 2.1 |
2068 | +Name: charmhelpers |
2069 | +Version: 0.20.23 |
2070 | +Summary: Helpers for Juju Charm development |
2071 | +Home-page: https://github.com/juju/charm-helpers |
2072 | +Author: Charmers |
2073 | +Author-email: juju@lists.ubuntu.com |
2074 | +License: UNKNOWN |
2075 | +Platform: UNKNOWN |
2076 | +Classifier: Intended Audience :: Information Technology |
2077 | +Classifier: Intended Audience :: System Administrators |
2078 | +Classifier: License :: OSI Approved :: Apache Software License |
2079 | +Classifier: Operating System :: POSIX :: Linux |
2080 | +Classifier: Programming Language :: Python |
2081 | +Classifier: Programming Language :: Python :: 2 |
2082 | +Classifier: Programming Language :: Python :: 2.7 |
2083 | +Classifier: Programming Language :: Python :: 3 |
2084 | +Classifier: Programming Language :: Python :: 3.6 |
2085 | +Classifier: Programming Language :: Python :: 3.7 |
2086 | +Classifier: Programming Language :: Python :: 3.8 |
2087 | +Requires-Dist: Jinja2 |
2088 | +Requires-Dist: PyYAML |
2089 | +Requires-Dist: Tempita |
2090 | +Requires-Dist: netaddr |
2091 | +Requires-Dist: pbr (!=2.1.0,>=2.0.0) |
2092 | +Requires-Dist: six |
2093 | + |
2094 | +CharmHelpers |badge| |
2095 | +-------------------- |
2096 | + |
2097 | +.. |badge| image:: https://github.com/juju/charm-helpers/actions/workflows/build.yml/badge.svg?branch=master |
2098 | + :target: https://github.com/juju/charm-helpers/actions/workflows/build.yml |
2099 | + |
2100 | +Overview |
2101 | +======== |
2102 | + |
2103 | +CharmHelpers provides an opinionated set of tools for building Juju charms. |
2104 | + |
2105 | +The full documentation is available online at: https://charm-helpers.readthedocs.io/ |
2106 | + |
2107 | +Common Usage Examples |
2108 | +===================== |
2109 | + |
2110 | +* interaction with charm-specific Juju unit agents via hook tools; |
2111 | +* processing of events and execution of decorated functions based on event names; |
2112 | +* handling of persistent storage between independent charm invocations; |
2113 | +* rendering of configuration file templates; |
2114 | +* modification of system configuration files; |
2115 | +* installation of packages; |
2116 | +* retrieval of machine-specific details; |
2117 | +* implementation of application-specific code reused in similar charms. |
2118 | + |
2119 | +Why Python? |
2120 | +=========== |
2121 | + |
2122 | +* Python is an extremely popular, easy to learn, and powerful language which is also common in automation tools; |
2123 | +* An interpreted language helps with charm portability across different CPU architectures; |
2124 | +* Doesn't require debugging symbols (just use pdb in-place); |
2125 | +* An author or a user is able to make debugging changes without recompiling a charm. |
2126 | + |
2127 | +Dev/Test |
2128 | +======== |
2129 | + |
2130 | +See the HACKING.md file for information about testing and development. |
2131 | + |
2132 | +License |
2133 | +======= |
2134 | + |
2135 | +Licensed under the Apache License, Version 2.0 (the "License"); |
2136 | +you may not use this file except in compliance with the License. |
2137 | +You may obtain a copy of the License at |
2138 | + |
2139 | + http://www.apache.org/licenses/LICENSE-2.0 |
2140 | + |
2141 | +Unless required by applicable law or agreed to in writing, software |
2142 | +distributed under the License is distributed on an "AS IS" BASIS, |
2143 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2144 | +See the License for the specific language governing permissions and |
2145 | +limitations under the License. |
2146 | + |
2147 | + |
2148 | + |
2149 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/RECORD b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/RECORD |
2150 | new file mode 100644 |
2151 | index 0000000..1265a34 |
2152 | --- /dev/null |
2153 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/RECORD |
2154 | @@ -0,0 +1,338 @@ |
2155 | +../../bin/charmsupport,sha256=z2Ahhl48jERwUMbWFry9nN3-HYE7ef6Yb9kyKcVG65k,910 |
2156 | +../../bin/chlp,sha256=TAx1ZeHF6RvrjVNTL6Z8EnYqVw6iaqM97ssF5Kqd6dc,134 |
2157 | +../../bin/salt-call,sha256=7GSY5yTe3yc5mXfCV7l2tLFPd1QFsF67-O4KbSCOhFM,190 |
2158 | +charmhelpers-0.20.23.dist-info/AUTHORS,sha256=LA1fKQDSel2F6WV5z1bCGJi15Kax16cmgcoIVOTU3Hc,9149 |
2159 | +charmhelpers-0.20.23.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 |
2160 | +charmhelpers-0.20.23.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358 |
2161 | +charmhelpers-0.20.23.dist-info/METADATA,sha256=UhVXDqyJGeKkJZu59SV0cZeY9z64kissYjjoGUZ042g,2867 |
2162 | +charmhelpers-0.20.23.dist-info/RECORD,, |
2163 | +charmhelpers-0.20.23.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92 |
2164 | +charmhelpers-0.20.23.dist-info/pbr.json,sha256=vtUyvqen8FVsRTiN4YXgDwa7-zr8YW5AI4_tVaJmoQU,47 |
2165 | +charmhelpers-0.20.23.dist-info/top_level.txt,sha256=5KmF7d1Uf0ZK3rqHxNFzsBbrycxZUoYLmaOB0762zNw,13 |
2166 | +charmhelpers/__init__.py,sha256=UZ_2r186iMSYkGIIgLWT0U81lZXy5OwGuwG4HFpR6P8,3593 |
2167 | +charmhelpers/__pycache__/__init__.cpython-38.pyc,, |
2168 | +charmhelpers/__pycache__/context.cpython-38.pyc,, |
2169 | +charmhelpers/__pycache__/coordinator.cpython-38.pyc,, |
2170 | +charmhelpers/__pycache__/osplatform.cpython-38.pyc,, |
2171 | +charmhelpers/__pycache__/version.cpython-38.pyc,, |
2172 | +charmhelpers/cli/README.rst,sha256=eAa7cMrPjilRFO3Fd8f-ZqXZcQduxsaFw6An6T2Mxtw,3101 |
2173 | +charmhelpers/cli/__init__.py,sha256=aWJPQAlZqfmC9dEvcbuQvXDD9Podo7wuf3NWSUd5CzI,6897 |
2174 | +charmhelpers/cli/__pycache__/__init__.cpython-38.pyc,, |
2175 | +charmhelpers/cli/__pycache__/benchmark.cpython-38.pyc,, |
2176 | +charmhelpers/cli/__pycache__/commands.cpython-38.pyc,, |
2177 | +charmhelpers/cli/__pycache__/hookenv.cpython-38.pyc,, |
2178 | +charmhelpers/cli/__pycache__/host.cpython-38.pyc,, |
2179 | +charmhelpers/cli/__pycache__/unitdata.cpython-38.pyc,, |
2180 | +charmhelpers/cli/benchmark.py,sha256=0EVA9bM9dEiGG5zo3ROxF_trVpnkJwhA1QKau-9i9hk,1296 |
2181 | +charmhelpers/cli/commands.py,sha256=5Clhh44FLf8vDGGrZFaaF2BHvRYw4tjtFk_WabxgVlM,1101 |
2182 | +charmhelpers/cli/hookenv.py,sha256=5J7_rfObmUqPX5ovbXTPminsRX1Z7anXxRVlC70f4ac,848 |
2183 | +charmhelpers/cli/host.py,sha256=Z5oXQ5d9vMN_tC2rTHSdx1I5tdQd6kL6QsB0uGrGS6M,1022 |
2184 | +charmhelpers/cli/unitdata.py,sha256=qiEEjaYdiHzM_LQ-SVTiV-3PAwMVqX1k-mXPg2fH5a0,1799 |
2185 | +charmhelpers/context.py,sha256=IaQv7Jwv5TtgNVLStDUPLYlLvpW80-j3-SsZIFRrL38,7575 |
2186 | +charmhelpers/contrib/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2187 | +charmhelpers/contrib/__pycache__/__init__.cpython-38.pyc,, |
2188 | +charmhelpers/contrib/__pycache__/python.cpython-38.pyc,, |
2189 | +charmhelpers/contrib/ansible/__init__.py,sha256=xV6QwHRr4p0J9bVi2gbGeQfnu1P0JBSPmkby96sdy_I,10197 |
2190 | +charmhelpers/contrib/ansible/__pycache__/__init__.cpython-38.pyc,, |
2191 | +charmhelpers/contrib/benchmark/__init__.py,sha256=qoJQb98jrVAbd3xRVQlpl2norUfS53kcDG_a36qXo-g,3768 |
2192 | +charmhelpers/contrib/benchmark/__pycache__/__init__.cpython-38.pyc,, |
2193 | +charmhelpers/contrib/charmhelpers/IMPORT,sha256=MAzGjhWluP6tDirtfiQAPQAW-aN1QIbTOC_LvQaRcM8,274 |
2194 | +charmhelpers/contrib/charmhelpers/__init__.py,sha256=zIsbK9HVGnJ2B_blpaIk1uqq6oB15UL8WBc7en8YhoE,7746 |
2195 | +charmhelpers/contrib/charmhelpers/__pycache__/__init__.cpython-38.pyc,, |
2196 | +charmhelpers/contrib/charmsupport/IMPORT,sha256=P5fXENEbVggQtH7Ug6rB6Cn4U1KzJO9lT2sDg1VZBRI,961 |
2197 | +charmhelpers/contrib/charmsupport/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2198 | +charmhelpers/contrib/charmsupport/__pycache__/__init__.cpython-38.pyc,, |
2199 | +charmhelpers/contrib/charmsupport/__pycache__/nrpe.cpython-38.pyc,, |
2200 | +charmhelpers/contrib/charmsupport/__pycache__/volumes.cpython-38.pyc,, |
2201 | +charmhelpers/contrib/charmsupport/nrpe.py,sha256=VbsK-rZbcPvN2RVZTQA2um-G53hgUkd0mnqvrF26eoc,19188 |
2202 | +charmhelpers/contrib/charmsupport/volumes.py,sha256=qaB_Lhk7fMWUwZ90fZ4d7Zwo-8ByDey6By9-Bjg4rVM,5928 |
2203 | +charmhelpers/contrib/database/__init__.py,sha256=uLfkEetO5N_jsH5lEDW7BdtiLrA2dlHStiHOv8NNp9Q,541 |
2204 | +charmhelpers/contrib/database/__pycache__/__init__.cpython-38.pyc,, |
2205 | +charmhelpers/contrib/database/__pycache__/mysql.cpython-38.pyc,, |
2206 | +charmhelpers/contrib/database/mysql.py,sha256=v9lYP5BP39vPTNuundpveL_FPetFD_M0Gg_d4OLZ7O4,30985 |
2207 | +charmhelpers/contrib/hahelpers/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2208 | +charmhelpers/contrib/hahelpers/__pycache__/__init__.cpython-38.pyc,, |
2209 | +charmhelpers/contrib/hahelpers/__pycache__/apache.cpython-38.pyc,, |
2210 | +charmhelpers/contrib/hahelpers/__pycache__/cluster.cpython-38.pyc,, |
2211 | +charmhelpers/contrib/hahelpers/apache.py,sha256=EvYrltL4p93JkpKYhupWbYu27gQPf7wyyqkUkhDB404,2854 |
2212 | +charmhelpers/contrib/hahelpers/cluster.py,sha256=XwfN6N81d_6FGGoXKmSb1esT4sQ9mUPp8K051A7C5z0,14761 |
2213 | +charmhelpers/contrib/hardening/README.hardening.md,sha256=fQ7ofcmpTSq0M9qAwcEqrHnBJMELfmXnhPZkXQoDWS8,1078 |
2214 | +charmhelpers/contrib/hardening/__init__.py,sha256=JyKIot_ny07U5ky-tWtzDfH_Mhsaa2JmZQFhF7P3JNs,579 |
2215 | +charmhelpers/contrib/hardening/__pycache__/__init__.cpython-38.pyc,, |
2216 | +charmhelpers/contrib/hardening/__pycache__/harden.cpython-38.pyc,, |
2217 | +charmhelpers/contrib/hardening/__pycache__/templating.cpython-38.pyc,, |
2218 | +charmhelpers/contrib/hardening/__pycache__/utils.cpython-38.pyc,, |
2219 | +charmhelpers/contrib/hardening/apache/__init__.py,sha256=AGnzufUxF09rFJMaKuYdpWPJ2VFZCt_DNm7RFjODDtY,664 |
2220 | +charmhelpers/contrib/hardening/apache/__pycache__/__init__.cpython-38.pyc,, |
2221 | +charmhelpers/contrib/hardening/apache/checks/__init__.py,sha256=lZrfeNvgGyC0T6DkjHTnTvpViHtCi8wAUTe958wltqk,1018 |
2222 | +charmhelpers/contrib/hardening/apache/checks/__pycache__/__init__.cpython-38.pyc,, |
2223 | +charmhelpers/contrib/hardening/apache/checks/__pycache__/config.cpython-38.pyc,, |
2224 | +charmhelpers/contrib/hardening/apache/checks/config.py,sha256=bQKeoExtlOxnw4JLfDHL6okcaE4Wir8iMT738UHawyQ,3634 |
2225 | +charmhelpers/contrib/hardening/apache/templates/99-hardening.conf,sha256=QiM3aU1ssjiO-sqtXuCyBZchHpmfCUoP3pUgLmJuaqg,864 |
2226 | +charmhelpers/contrib/hardening/apache/templates/alias.conf,sha256=bCmG5CFSJTytjJtbHNzNmJKKZyMJuR_stS7whbZzggM,1198 |
2227 | +charmhelpers/contrib/hardening/audits/__init__.py,sha256=aKraPvxRTLrDE8lP0Sr0sNuJyNCUHp3o84XYoK6cCR8,2052 |
2228 | +charmhelpers/contrib/hardening/audits/__pycache__/__init__.cpython-38.pyc,, |
2229 | +charmhelpers/contrib/hardening/audits/__pycache__/apache.cpython-38.pyc,, |
2230 | +charmhelpers/contrib/hardening/audits/__pycache__/apt.cpython-38.pyc,, |
2231 | +charmhelpers/contrib/hardening/audits/__pycache__/file.cpython-38.pyc,, |
2232 | +charmhelpers/contrib/hardening/audits/apache.py,sha256=FvQVqwdJr4XbE2s8EYqbwUc6UipFpdFB1ejEzqQb_eE,3652 |
2233 | +charmhelpers/contrib/hardening/audits/apt.py,sha256=lzFG-GvQzuNxTRZmRFC5GFIpN4sQOc-9EwsQA6vdjy0,3529 |
2234 | +charmhelpers/contrib/hardening/audits/file.py,sha256=_GGN2oRvRaW60wEtHyn6ptFBCs5NNTQZj0Y5SsVfB5I,19624 |
2235 | +charmhelpers/contrib/hardening/defaults/apache.yaml,sha256=trCCi7WX20kklq5oHTQsa5bmiZ2WY4kGkjwSIaxOvgw,608 |
2236 | +charmhelpers/contrib/hardening/defaults/apache.yaml.schema,sha256=3lUtLjIJIV4eMVP2kcrtt-qqZi-Ju_l9hegZVDpIip4,303 |
2237 | +charmhelpers/contrib/hardening/defaults/mysql.yaml,sha256=AFxAc5r3A_dkMA40Wbpa7_gzgL4SjOS3aguMT6NRkS4,1655 |
2238 | +charmhelpers/contrib/hardening/defaults/mysql.yaml.schema,sha256=incmlBGYQ33sKWoojIq471_D5LBfCL6rMkHbwt7gfGU,393 |
2239 | +charmhelpers/contrib/hardening/defaults/os.yaml,sha256=v_yf92FkRtcR2t_CruZgdZjZuuExwNY8ZrzTAFDN1Vg,1928 |
2240 | +charmhelpers/contrib/hardening/defaults/os.yaml.schema,sha256=3HuBijlL_go6xDSi956SoPNDfBwsverh-FK-GliUyWA,908 |
2241 | +charmhelpers/contrib/hardening/defaults/ssh.yaml,sha256=VHBFUbR_By5fzUtbVXr0A3ZusyE-oM-AAB3c9hA3sj8,1537 |
2242 | +charmhelpers/contrib/hardening/defaults/ssh.yaml.schema,sha256=xjyI1eo-sNH_WiDNImmzYy4NZqUgaCyRb6_JS3O4LA8,852 |
2243 | +charmhelpers/contrib/hardening/harden.py,sha256=1OGzrpl-pj7G9LDZmpV28YP5AH9Dn6koDOJ7vKEwNzE,3909 |
2244 | +charmhelpers/contrib/hardening/host/__init__.py,sha256=AGnzufUxF09rFJMaKuYdpWPJ2VFZCt_DNm7RFjODDtY,664 |
2245 | +charmhelpers/contrib/hardening/host/__pycache__/__init__.cpython-38.pyc,, |
2246 | +charmhelpers/contrib/hardening/host/checks/__init__.py,sha256=aIN_iRFqI1g-dPaEXT3C9yIsnlD2xRV4n_xvU120geY,1439 |
2247 | +charmhelpers/contrib/hardening/host/checks/__pycache__/__init__.cpython-38.pyc,, |
2248 | +charmhelpers/contrib/hardening/host/checks/__pycache__/apt.cpython-38.pyc,, |
2249 | +charmhelpers/contrib/hardening/host/checks/__pycache__/limits.cpython-38.pyc,, |
2250 | +charmhelpers/contrib/hardening/host/checks/__pycache__/login.cpython-38.pyc,, |
2251 | +charmhelpers/contrib/hardening/host/checks/__pycache__/minimize_access.cpython-38.pyc,, |
2252 | +charmhelpers/contrib/hardening/host/checks/__pycache__/pam.cpython-38.pyc,, |
2253 | +charmhelpers/contrib/hardening/host/checks/__pycache__/profile.cpython-38.pyc,, |
2254 | +charmhelpers/contrib/hardening/host/checks/__pycache__/securetty.cpython-38.pyc,, |
2255 | +charmhelpers/contrib/hardening/host/checks/__pycache__/suid_sgid.cpython-38.pyc,, |
2256 | +charmhelpers/contrib/hardening/host/checks/__pycache__/sysctl.cpython-38.pyc,, |
2257 | +charmhelpers/contrib/hardening/host/checks/apt.py,sha256=l2kKOfqp2zQLUNRWdBlzE9FGQ9_AZqVYwvgNhM-FB0g,1255 |
2258 | +charmhelpers/contrib/hardening/host/checks/limits.py,sha256=oMLlcmw8O8eWmzFkAXT7zUju3IIOKMwgB9iocwmgPRI,2015 |
2259 | +charmhelpers/contrib/hardening/host/checks/login.py,sha256=xdlp9kjYXHhFeBoXKlSCM_wQwZ0hH3NjgwBv1KTNVRM,2514 |
2260 | +charmhelpers/contrib/hardening/host/checks/minimize_access.py,sha256=Px1OQ96RNSA3tWFYW0eWkIk0elnWsjlAyhp0n-FMy5Q,1849 |
2261 | +charmhelpers/contrib/hardening/host/checks/pam.py,sha256=dhjqQNsBPQ82jqQ-FDmxuKyI-QT7nVfPLApO5DhBVTQ,4042 |
2262 | +charmhelpers/contrib/hardening/host/checks/profile.py,sha256=dC-DBwfHvSALGWzsPc8p6VTORn25jO7sjtVPK4m7XJY,1905 |
2263 | +charmhelpers/contrib/hardening/host/checks/securetty.py,sha256=SA7Ln9dW1BOQMohVKrx1fJTcNgZXfop3cnT9hmbkz5U,1283 |
2264 | +charmhelpers/contrib/hardening/host/checks/suid_sgid.py,sha256=PaNAU2oJlz6drXWpkIhtIe4rxbazyI9CXZvr21vb6jc,5057 |
2265 | +charmhelpers/contrib/hardening/host/checks/sysctl.py,sha256=o-ny9OntomnTKP-iaeFyh-jtLexG04-11Y3vGOSNGAw,7421 |
2266 | +charmhelpers/contrib/hardening/host/templates/10.hardcore.conf,sha256=32p-Xp6nTdYqDwCRkfHetIBQ9M8xdAFfMM4T0W03svk,435 |
2267 | +charmhelpers/contrib/hardening/host/templates/99-hardening.sh,sha256=YqlQ86pwqXHITmNWpjkcKsABplMfFdG2_CbaEPCFvJI,65 |
2268 | +charmhelpers/contrib/hardening/host/templates/99-juju-hardening.conf,sha256=7-ufC_2dpUh43flvsUmhPeUnJObn0xRbjCGU7Bjm7is,340 |
2269 | +charmhelpers/contrib/hardening/host/templates/login.defs,sha256=bilHHMKXNW08fCYrACqHSUx69M9Bzgf9mIfUepK8fi0,11495 |
2270 | +charmhelpers/contrib/hardening/host/templates/modules,sha256=QVulAENAQNjAKZSw3GvClf4lTk3fLF9cgqN8ErKB5S0,1726 |
2271 | +charmhelpers/contrib/hardening/host/templates/passwdqc.conf,sha256=DoJQ4pJNZyybxy9rsoMDiQVZT6mUslrzY_73gftlwYw,453 |
2272 | +charmhelpers/contrib/hardening/host/templates/pinerolo_profile.sh,sha256=L3HzvAHokRNX1SVQ8dUG8xQYn7L2iBtLCpWTbIiyIzU,472 |
2273 | +charmhelpers/contrib/hardening/host/templates/securetty,sha256=Ds3sazz6fMgEI0oMLRWXt-TOp5gF2Fk8movVDzSLASk,419 |
2274 | +charmhelpers/contrib/hardening/host/templates/tally2,sha256=6VxdzzPJIz_r2QEZfD55U6cB_rkgQ-hbsxRnoTEB4eQ,569 |
2275 | +charmhelpers/contrib/hardening/mysql/__init__.py,sha256=AGnzufUxF09rFJMaKuYdpWPJ2VFZCt_DNm7RFjODDtY,664 |
2276 | +charmhelpers/contrib/hardening/mysql/__pycache__/__init__.cpython-38.pyc,, |
2277 | +charmhelpers/contrib/hardening/mysql/checks/__init__.py,sha256=-iXZm9k4HINfFmcOmx3dsS-r7ScgLkeBATda-pV7vcA,1014 |
2278 | +charmhelpers/contrib/hardening/mysql/checks/__pycache__/__init__.cpython-38.pyc,, |
2279 | +charmhelpers/contrib/hardening/mysql/checks/__pycache__/config.cpython-38.pyc,, |
2280 | +charmhelpers/contrib/hardening/mysql/checks/config.py,sha256=tmp5IAQTuLrhQWV4NCwljHELrK6sIcwtCzj6cHSW5pM,2989 |
2281 | +charmhelpers/contrib/hardening/mysql/templates/hardening.cnf,sha256=6ECbDt-t4PYHuC1yeirNmjo4qA0ThmYD36M_L-I3dPM,457 |
2282 | +charmhelpers/contrib/hardening/ssh/__init__.py,sha256=AGnzufUxF09rFJMaKuYdpWPJ2VFZCt_DNm7RFjODDtY,664 |
2283 | +charmhelpers/contrib/hardening/ssh/__pycache__/__init__.cpython-38.pyc,, |
2284 | +charmhelpers/contrib/hardening/ssh/checks/__init__.py,sha256=hR00G4AUdIo26vzkTOq9q_nxAWqqo7Y752ITblsfRBw,1006 |
2285 | +charmhelpers/contrib/hardening/ssh/checks/__pycache__/__init__.cpython-38.pyc,, |
2286 | +charmhelpers/contrib/hardening/ssh/checks/__pycache__/config.cpython-38.pyc,, |
2287 | +charmhelpers/contrib/hardening/ssh/checks/config.py,sha256=nh6_HrNc7HRvpIASs28bNdF9-1lIx095FHp8SB7LOlE,18949 |
2288 | +charmhelpers/contrib/hardening/ssh/templates/ssh_config,sha256=Tpcaxl4_Im3Ol65mp2dlJQ3_qWqNtMkk8LK_PxVrIgQ,2028 |
2289 | +charmhelpers/contrib/hardening/ssh/templates/sshd_config,sha256=aU-pRJCa8IDdgdlfzRYrNn0KAOYFtMofFWutAOWVRt4,4488 |
2290 | +charmhelpers/contrib/hardening/templating.py,sha256=Iiw5lC6FIadGdH63CrMOuYX_7bGHwtltMwAhJWNOyrA,2447 |
2291 | +charmhelpers/contrib/hardening/utils.py,sha256=U5F3cH99tkMO6Eoi5BCnc0r8OmdkYQraeDxGKunMN2E,5193 |
2292 | +charmhelpers/contrib/mellanox/__init__.py,sha256=Tw33cKAnl0OzKf_D5VqVyr__eWnyW6xHvhzG6SJUsps,574 |
2293 | +charmhelpers/contrib/mellanox/__pycache__/__init__.cpython-38.pyc,, |
2294 | +charmhelpers/contrib/mellanox/__pycache__/infiniband.cpython-38.pyc,, |
2295 | +charmhelpers/contrib/mellanox/infiniband.py,sha256=UXjjFu9N8iY9YOAgqZlW8IOkwOjbBVnrbfsUICMhaVU,3494 |
2296 | +charmhelpers/contrib/network/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2297 | +charmhelpers/contrib/network/__pycache__/__init__.cpython-38.pyc,, |
2298 | +charmhelpers/contrib/network/__pycache__/ip.cpython-38.pyc,, |
2299 | +charmhelpers/contrib/network/__pycache__/ufw.cpython-38.pyc,, |
2300 | +charmhelpers/contrib/network/ip.py,sha256=FurNn_p91M6RsRM6grcmnetJvQuU4nAk_1MmuYa3qyM,19187 |
2301 | +charmhelpers/contrib/network/ovs/__init__.py,sha256=JyYO4EJam7pGsOovu9Jo7j_6YAM2oQ3__VyKiLpQUJI,27043 |
2302 | +charmhelpers/contrib/network/ovs/__pycache__/__init__.cpython-38.pyc,, |
2303 | +charmhelpers/contrib/network/ovs/__pycache__/ovn.cpython-38.pyc,, |
2304 | +charmhelpers/contrib/network/ovs/__pycache__/ovsdb.cpython-38.pyc,, |
2305 | +charmhelpers/contrib/network/ovs/__pycache__/utils.cpython-38.pyc,, |
2306 | +charmhelpers/contrib/network/ovs/ovn.py,sha256=FOMEBmqgb-9Z9n4nhy69Zq8JnxxkvZvlE2FN1u8fDM4,8627 |
2307 | +charmhelpers/contrib/network/ovs/ovsdb.py,sha256=VOPEfwTorL4Ig7Tu_bv-gPsxS-FBzZIKdgA-Exvg03M,8776 |
2308 | +charmhelpers/contrib/network/ovs/utils.py,sha256=D6d4ZRqnJzP2iHQYsHzmFsXlSY-7wMFS5zgcyWwvgl8,948 |
2309 | +charmhelpers/contrib/network/ufw.py,sha256=1-OSr1EhFcIW1Tuz_CzB-h7Lv4gP-bSYI5dUGmQPuhA,12722 |
2310 | +charmhelpers/contrib/openstack/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2311 | +charmhelpers/contrib/openstack/__pycache__/__init__.cpython-38.pyc,, |
2312 | +charmhelpers/contrib/openstack/__pycache__/alternatives.cpython-38.pyc,, |
2313 | +charmhelpers/contrib/openstack/__pycache__/cert_utils.cpython-38.pyc,, |
2314 | +charmhelpers/contrib/openstack/__pycache__/context.cpython-38.pyc,, |
2315 | +charmhelpers/contrib/openstack/__pycache__/deferred_events.cpython-38.pyc,, |
2316 | +charmhelpers/contrib/openstack/__pycache__/exceptions.cpython-38.pyc,, |
2317 | +charmhelpers/contrib/openstack/__pycache__/ip.cpython-38.pyc,, |
2318 | +charmhelpers/contrib/openstack/__pycache__/keystone.cpython-38.pyc,, |
2319 | +charmhelpers/contrib/openstack/__pycache__/neutron.cpython-38.pyc,, |
2320 | +charmhelpers/contrib/openstack/__pycache__/policy_rcd.cpython-38.pyc,, |
2321 | +charmhelpers/contrib/openstack/__pycache__/policyd.cpython-38.pyc,, |
2322 | +charmhelpers/contrib/openstack/__pycache__/ssh_migrations.cpython-38.pyc,, |
2323 | +charmhelpers/contrib/openstack/__pycache__/templating.cpython-38.pyc,, |
2324 | +charmhelpers/contrib/openstack/__pycache__/utils.cpython-38.pyc,, |
2325 | +charmhelpers/contrib/openstack/__pycache__/vaultlocker.cpython-38.pyc,, |
2326 | +charmhelpers/contrib/openstack/alternatives.py,sha256=WJQw90efeFIxtuXgbRpOYOPjwT1pBnZHgyWc0uL496A,1472 |
2327 | +charmhelpers/contrib/openstack/audits/__init__.py,sha256=SWgrwhWuHOP45o4CT-FX6xzHRz83JWXZ1I1WZI8WUL4,6371 |
2328 | +charmhelpers/contrib/openstack/audits/__pycache__/__init__.cpython-38.pyc,, |
2329 | +charmhelpers/contrib/openstack/audits/__pycache__/openstack_security_guide.cpython-38.pyc,, |
2330 | +charmhelpers/contrib/openstack/audits/openstack_security_guide.py,sha256=KNnYfimCparl-HgoDOnuMndSUghmxUjgASzulzZds48,9893 |
2331 | +charmhelpers/contrib/openstack/cert_utils.py,sha256=OLAos14O0n0ThbGRp6568hLcdWUkAIwpSD0Pvy9L9g4,15720 |
2332 | +charmhelpers/contrib/openstack/context.py,sha256=T_VZe_sCJSPUPH69bCo6e_Y-3ZpOHznxk8X3Z1HUuT4,123351 |
2333 | +charmhelpers/contrib/openstack/deferred_events.py,sha256=IJTL4GIFe5oQPzu1S-pfledau4jlV5sNy6R-tF9UrWQ,12410 |
2334 | +charmhelpers/contrib/openstack/exceptions.py,sha256=xbtpzWwFE7s4zAuWhUaaTeZdQIp-p_EkTaVA-5mZkx0,870 |
2335 | +charmhelpers/contrib/openstack/files/__init__.py,sha256=PJ_onBF2kxnou5_JEFsqozUor08PhKQHOQ2f-_DxLUc,669 |
2336 | +charmhelpers/contrib/openstack/files/__pycache__/__init__.cpython-38.pyc,, |
2337 | +charmhelpers/contrib/openstack/files/__pycache__/policy_rc_d_script.cpython-38.pyc,, |
2338 | +charmhelpers/contrib/openstack/files/check_haproxy.sh,sha256=6qjVzMnm9iX6SzGQOhzGMzeSZNh5e50T654g4eVE_1Q,1041 |
2339 | +charmhelpers/contrib/openstack/files/check_haproxy_queue_depth.sh,sha256=WxfWaAP82ZQlyo6pDJCqPH2zyPa5HqHzzZL49cA39T0,968 |
2340 | +charmhelpers/contrib/openstack/files/policy_rc_d_script.py,sha256=SAuPN2xZl3hUz_gROwXU9_DK66tNfTLHBvxVF6-qAM4,6052 |
2341 | +charmhelpers/contrib/openstack/ha/__init__.py,sha256=Tw33cKAnl0OzKf_D5VqVyr__eWnyW6xHvhzG6SJUsps,574 |
2342 | +charmhelpers/contrib/openstack/ha/__pycache__/__init__.cpython-38.pyc,, |
2343 | +charmhelpers/contrib/openstack/ha/__pycache__/utils.cpython-38.pyc,, |
2344 | +charmhelpers/contrib/openstack/ha/utils.py,sha256=gyIil5PvyLVYBpumm4LL6BxXPUVZlZBjIFlL6Xy6Z_Q,12044 |
2345 | +charmhelpers/contrib/openstack/ip.py,sha256=W_dj3lW8uKxfUWvWqnE0_NQUTF_G9eWjdIliZ0ijhog,7940 |
2346 | +charmhelpers/contrib/openstack/keystone.py,sha256=ikFV8Ajj7BkkQ-xBp7Mg7370eMyUC4Gk3QxurNwNXHE,6550 |
2347 | +charmhelpers/contrib/openstack/neutron.py,sha256=-t5eBoB6S_B1Of2ZF0By0NdbVopTz2ROYrr2GXKztFc,12738 |
2348 | +charmhelpers/contrib/openstack/policy_rcd.py,sha256=WfbCKfG-vZauxKTVMEb4axDEHa-pzo1xacbGAQZPFeg,5783 |
2349 | +charmhelpers/contrib/openstack/policyd.py,sha256=Xm9y2mBUCCFDE8ex9i0w3JsqdoCbeuLdOyApWIFYfFM,33050 |
2350 | +charmhelpers/contrib/openstack/ssh_migrations.py,sha256=PM4ndr5BDRagRH6EIfDSxeNWFcXFogGWhkBcBoCW_LI,14069 |
2351 | +charmhelpers/contrib/openstack/templates/__init__.py,sha256=PJ_onBF2kxnou5_JEFsqozUor08PhKQHOQ2f-_DxLUc,669 |
2352 | +charmhelpers/contrib/openstack/templates/__pycache__/__init__.cpython-38.pyc,, |
2353 | +charmhelpers/contrib/openstack/templates/ceph.conf,sha256=K88GaxfoZQaGV0YgFhyOc0btnxeG0zwIXcHwO_oOhSU,819 |
2354 | +charmhelpers/contrib/openstack/templates/git.upstart,sha256=odPhJchOT0dyDodCdXhOpaFMDOL-2li2jJ2jutcjP7c,541 |
2355 | +charmhelpers/contrib/openstack/templates/haproxy.cfg,sha256=6F3lnjD2r1cbTsCrwkTdRgnnZgCpXGSKzxetMY-Gdpo,2671 |
2356 | +charmhelpers/contrib/openstack/templates/logrotate,sha256=gGK4qTsgCZ6rSb7vulAAbTpmdzpGVc0B_a_88sLTjAs,181 |
2357 | +charmhelpers/contrib/openstack/templates/memcached.conf,sha256=IkPMWuHzbnwB2DKslUAEiuQk4np400NYn1fDP9T3Vso,1714 |
2358 | +charmhelpers/contrib/openstack/templates/openstack_https_frontend,sha256=xvwUbAw_nAXTiPzvonZlJVygVCQZ6GzAWRU69J4vgq8,1347 |
2359 | +charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf,sha256=xvwUbAw_nAXTiPzvonZlJVygVCQZ6GzAWRU69J4vgq8,1347 |
2360 | +charmhelpers/contrib/openstack/templates/section-ceph-bluestore-compression,sha256=cqD_o3pJIM0O_eDhWyQZOohUpD98MARIvdyQzDo3cJE,1335 |
2361 | +charmhelpers/contrib/openstack/templates/section-keystone-authtoken,sha256=gfVZd-o7yXDO2keDESwdoSZiIDXtDwun5dWS1EI3NeI,400 |
2362 | +charmhelpers/contrib/openstack/templates/section-keystone-authtoken-legacy,sha256=ml9SRXkQ1lKhNtZhRT2ADGm7oUFAObFxfT8DpYnKbRE,406 |
2363 | +charmhelpers/contrib/openstack/templates/section-keystone-authtoken-mitaka,sha256=q0byZxLux3J2moLGJCGBzX_DQ-JvUCS6aVwFBUZ12WQ,772 |
2364 | +charmhelpers/contrib/openstack/templates/section-keystone-authtoken-v3only,sha256=4mDE-vdsn_9VD9bp_AYL4FLrX4FpMfuuZdloMuqRLWo,256 |
2365 | +charmhelpers/contrib/openstack/templates/section-oslo-cache,sha256=S6W7acRDZGh3UR29aYcxwulC3MWCRIpaB9lL9KG2OwI,130 |
2366 | +charmhelpers/contrib/openstack/templates/section-oslo-messaging-rabbit,sha256=90tfS3oujFv6MlIxPCJZsVxtXHoB4fo1sHKxyPvhTlU,211 |
2367 | +charmhelpers/contrib/openstack/templates/section-oslo-messaging-rabbit-ocata,sha256=9DU9eMzwp5OA2MqfC-fS8ehCGsb3lMIsQYiXdUpRoEE,222 |
2368 | +charmhelpers/contrib/openstack/templates/section-oslo-middleware,sha256=_Ie2iLTToU2FOiEMsNsS66faNAMSi0oz2yuY2Vbfo4E,71 |
2369 | +charmhelpers/contrib/openstack/templates/section-oslo-notifications,sha256=L-lkuVhwpBdqbx-XkE0828I_APklrhD0P-B0b4OsRa0,387 |
2370 | +charmhelpers/contrib/openstack/templates/section-placement,sha256=YGoDFtueuClFKDnOhBoSCm-k-tTKi2y3lmZuRI25FsM,556 |
2371 | +charmhelpers/contrib/openstack/templates/section-rabbitmq-oslo,sha256=81fX6vXsYrNSS_50bieIQOWlmMVfObRSEBU8KCHYfRQ,598 |
2372 | +charmhelpers/contrib/openstack/templates/section-zeromq,sha256=qBteJtj4tIAEOOc7kkAvnabDTpSyQKUNbNhUraEvoy4,353 |
2373 | +charmhelpers/contrib/openstack/templates/vendor_data.json,sha256=G0Jt3EfboVTfY-htXGN3IobJEp9apB0sRuEUb0KHNVU,22 |
2374 | +charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf,sha256=8K4SrNYTq6SjWwfHB9KqAsVi0kkxPbRud3SO4VYfKRI,2825 |
2375 | +charmhelpers/contrib/openstack/templates/wsgi-openstack-metadata.conf,sha256=8K4SrNYTq6SjWwfHB9KqAsVi0kkxPbRud3SO4VYfKRI,2825 |
2376 | +charmhelpers/contrib/openstack/templating.py,sha256=-Pr-JC7a46C-bYVKzRmKyY2S3XGyGmcULRNiqMh9V_k,14743 |
2377 | +charmhelpers/contrib/openstack/utils.py,sha256=5E903-fSr8w-B2HX-LoDMEogZUq-ujWYBcVsKefcl8g,91050 |
2378 | +charmhelpers/contrib/openstack/vaultlocker.py,sha256=a6jDooWjlHNHR0zLlekdBnKbyQzPBF4k0viT7j6CKKI,6995 |
2379 | +charmhelpers/contrib/peerstorage/__init__.py,sha256=q_48JDfhHqpzSwCLgHFmxgOdF23ftC23p3tB0ofANQk,9610 |
2380 | +charmhelpers/contrib/peerstorage/__pycache__/__init__.cpython-38.pyc,, |
2381 | +charmhelpers/contrib/python.py,sha256=neyhpDKISpH_kJXrwrS85vckFrVMR11i5b6jdKzy31c,886 |
2382 | +charmhelpers/contrib/saltstack/__init__.py,sha256=cBZHwOETTMXLfW8V7jZZMYgLzycBZyHD0rG9jEGtIIw,3485 |
2383 | +charmhelpers/contrib/saltstack/__pycache__/__init__.cpython-38.pyc,, |
2384 | +charmhelpers/contrib/ssl/__init__.py,sha256=75wkn7oclRerwNYmMkrzc09UQ3qOzNL9jhZhmYrA9zA,3734 |
2385 | +charmhelpers/contrib/ssl/__pycache__/__init__.cpython-38.pyc,, |
2386 | +charmhelpers/contrib/ssl/__pycache__/service.cpython-38.pyc,, |
2387 | +charmhelpers/contrib/ssl/service.py,sha256=0JA_BjNzvNHRFjz0MD2DZcu3bqww0-4mUxzDMivP_0o,9303 |
2388 | +charmhelpers/contrib/storage/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2389 | +charmhelpers/contrib/storage/__pycache__/__init__.cpython-38.pyc,, |
2390 | +charmhelpers/contrib/storage/linux/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2391 | +charmhelpers/contrib/storage/linux/__pycache__/__init__.cpython-38.pyc,, |
2392 | +charmhelpers/contrib/storage/linux/__pycache__/bcache.cpython-38.pyc,, |
2393 | +charmhelpers/contrib/storage/linux/__pycache__/ceph.cpython-38.pyc,, |
2394 | +charmhelpers/contrib/storage/linux/__pycache__/loopback.cpython-38.pyc,, |
2395 | +charmhelpers/contrib/storage/linux/__pycache__/lvm.cpython-38.pyc,, |
2396 | +charmhelpers/contrib/storage/linux/__pycache__/utils.cpython-38.pyc,, |
2397 | +charmhelpers/contrib/storage/linux/bcache.py,sha256=zgsF8FEFvPDIyNgGIG74hDzPTnXYzJccq6KdfzxWC5k,2294 |
2398 | +charmhelpers/contrib/storage/linux/ceph.py,sha256=9ks9H04lXQneQ0WjNF2e8d71Cyc8QAZSqZQuw3qJAFo,87100 |
2399 | +charmhelpers/contrib/storage/linux/loopback.py,sha256=bWvQlo4c_6ylUyVmTZxQAcCcObeSvSb4o8tMZloW8ZU,2771 |
2400 | +charmhelpers/contrib/storage/linux/lvm.py,sha256=E9VNULuLkr1DeVIzGQ9RL2PwBtY_uVutHZ5brV7PM3Y,5582 |
2401 | +charmhelpers/contrib/storage/linux/utils.py,sha256=WxU2NG3d4v-CWMWir8Ga-m1kdujZYqaTt7M8O4vvNdo,4018 |
2402 | +charmhelpers/contrib/sysctl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 |
2403 | +charmhelpers/contrib/sysctl/__pycache__/__init__.cpython-38.pyc,, |
2404 | +charmhelpers/contrib/sysctl/__pycache__/watermark_scale_factor.cpython-38.pyc,, |
2405 | +charmhelpers/contrib/sysctl/watermark_scale_factor.py,sha256=BQtmmlq0Nx6ScLMTzIl_L_y7N7IEsY0MskkFU_YahLE,3388 |
2406 | +charmhelpers/contrib/templating/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2407 | +charmhelpers/contrib/templating/__pycache__/__init__.cpython-38.pyc,, |
2408 | +charmhelpers/contrib/templating/__pycache__/contexts.cpython-38.pyc,, |
2409 | +charmhelpers/contrib/templating/__pycache__/jinja.cpython-38.pyc,, |
2410 | +charmhelpers/contrib/templating/__pycache__/pyformat.cpython-38.pyc,, |
2411 | +charmhelpers/contrib/templating/contexts.py,sha256=bhMlQTNFWF83dq7bW5O9a3hstuDVQxAkkJeIxCFrB-g,5240 |
2412 | +charmhelpers/contrib/templating/jinja.py,sha256=SooB8IPYPGXKAfI_z3IRyFkL3aIsigz481v2Nk-deaU,1761 |
2413 | +charmhelpers/contrib/templating/pyformat.py,sha256=XEiPZSPbI_gvJKG8ORzqnFcNOrJyILKbPqvRMyYWQu8,935 |
2414 | +charmhelpers/contrib/unison/__init__.py,sha256=WkvPoA9bJAzHf04rguoAlH-UE-fzRrwJAT7XzV5W7gI,10262 |
2415 | +charmhelpers/contrib/unison/__pycache__/__init__.cpython-38.pyc,, |
2416 | +charmhelpers/coordinator.py,sha256=brnN4lezo2SmzW5EAAHECcFx0_nma9ewA2FuIGhHxMA,23485 |
2417 | +charmhelpers/core/__init__.py,sha256=cgDOTi6NEduIPlGmBYi69fC9cCaht22kCre0am-M2rk,584 |
2418 | +charmhelpers/core/__pycache__/__init__.cpython-38.pyc,, |
2419 | +charmhelpers/core/__pycache__/decorators.cpython-38.pyc,, |
2420 | +charmhelpers/core/__pycache__/files.cpython-38.pyc,, |
2421 | +charmhelpers/core/__pycache__/fstab.cpython-38.pyc,, |
2422 | +charmhelpers/core/__pycache__/hookenv.cpython-38.pyc,, |
2423 | +charmhelpers/core/__pycache__/host.cpython-38.pyc,, |
2424 | +charmhelpers/core/__pycache__/hugepage.cpython-38.pyc,, |
2425 | +charmhelpers/core/__pycache__/kernel.cpython-38.pyc,, |
2426 | +charmhelpers/core/__pycache__/strutils.cpython-38.pyc,, |
2427 | +charmhelpers/core/__pycache__/sysctl.cpython-38.pyc,, |
2428 | +charmhelpers/core/__pycache__/templating.cpython-38.pyc,, |
2429 | +charmhelpers/core/__pycache__/unitdata.cpython-38.pyc,, |
2430 | +charmhelpers/core/decorators.py,sha256=mdGH6gfxeA0-lbDG3MTFHvM8DzM1zw9dhWH8gR8TdVY,3217 |
2431 | +charmhelpers/core/files.py,sha256=rrwh-nvq4TrluH3oWPwA-tBpBNDTX3K9tJwsSQC3XxM,1657 |
2432 | +charmhelpers/core/fstab.py,sha256=DF7KX0VeTEbaI3F2ESqWDQZ7cCtyX4xT3-zHqtRT6jk,4189 |
2433 | +charmhelpers/core/hookenv.py,sha256=NkCPLGSrkr9gVriOomSYGPKPkXCOpxTTynxrtiWETP4,51829 |
2434 | +charmhelpers/core/host.py,sha256=vzl114O0YeL6ngV8URbn8fZzj8TASiIUTumL2fzjAf0,48084 |
2435 | +charmhelpers/core/host_factory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 |
2436 | +charmhelpers/core/host_factory/__pycache__/__init__.cpython-38.pyc,, |
2437 | +charmhelpers/core/host_factory/__pycache__/centos.cpython-38.pyc,, |
2438 | +charmhelpers/core/host_factory/__pycache__/ubuntu.cpython-38.pyc,, |
2439 | +charmhelpers/core/host_factory/centos.py,sha256=TixRcKI_DC65GhC6N0WXwTVbu7lLuwkzkkLEQMd1qII,1924 |
2440 | +charmhelpers/core/host_factory/ubuntu.py,sha256=rXA1T3GpnOJZZEkAeHz8rWz-vndTkHF-dMz-WioyrIA,2914 |
2441 | +charmhelpers/core/hugepage.py,sha256=uek21StWW-qxGB0huKIvhfRCwp6Mw-lsHuoVKd2amu0,2659 |
2442 | +charmhelpers/core/kernel.py,sha256=jLutRvmQLyJvFa8MDeKmjY7iOHO8YOsaHpgbH32nY08,2178 |
2443 | +charmhelpers/core/kernel_factory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 |
2444 | +charmhelpers/core/kernel_factory/__pycache__/__init__.cpython-38.pyc,, |
2445 | +charmhelpers/core/kernel_factory/__pycache__/centos.cpython-38.pyc,, |
2446 | +charmhelpers/core/kernel_factory/__pycache__/ubuntu.cpython-38.pyc,, |
2447 | +charmhelpers/core/kernel_factory/centos.py,sha256=tOBPiIq9Mmp7Ee2abWqz7WqRoiRf1PX4mxORCzehk70,538 |
2448 | +charmhelpers/core/kernel_factory/ubuntu.py,sha256=oGKJ5SxbgagjvY6cnUOsGN0WFuFu3XHipJjQltZZIkk,406 |
2449 | +charmhelpers/core/services/__init__.py,sha256=ZfT_5FZslewnV9B7Y9r-W_yK0HwtET8jUeKxXe9lhZU,644 |
2450 | +charmhelpers/core/services/__pycache__/__init__.cpython-38.pyc,, |
2451 | +charmhelpers/core/services/__pycache__/base.cpython-38.pyc,, |
2452 | +charmhelpers/core/services/__pycache__/helpers.cpython-38.pyc,, |
2453 | +charmhelpers/core/services/base.py,sha256=6vrPDlGUZ3Ev0ncPk80qdDQib8QQEdUVtPiRChl7x3I,14587 |
2454 | +charmhelpers/core/services/helpers.py,sha256=mV4MctagKkVDCQNsHpsJfcxBO7YJgwKGF0rceE63A0k,10684 |
2455 | +charmhelpers/core/strutils.py,sha256=qWEWkC9vfLPXxOfDt6AxmW6IJsJjKP_q6QxHEuGoXFs,3992 |
2456 | +charmhelpers/core/sysctl.py,sha256=8uJANDAIUzSefi5wgqWlBr0vMlM5-OipxgLB76LDeZI,2348 |
2457 | +charmhelpers/core/templating.py,sha256=iXknCzzlickGwTjZnQ5g5cE0O36HZeWB_KXnjUdSJBI,3567 |
2458 | +charmhelpers/core/unitdata.py,sha256=oN4Dv6ZB0l0ajK1Q7ZmFdFXNtlObBRT_BMZWro9Fe8U,16345 |
2459 | +charmhelpers/fetch/__init__.py,sha256=FNpWidcPJSEvlK1SLgZF2FVp-dmz-6dMS-Yy-j7mKj4,6861 |
2460 | +charmhelpers/fetch/__pycache__/__init__.cpython-38.pyc,, |
2461 | +charmhelpers/fetch/__pycache__/archiveurl.cpython-38.pyc,, |
2462 | +charmhelpers/fetch/__pycache__/bzrurl.cpython-38.pyc,, |
2463 | +charmhelpers/fetch/__pycache__/centos.cpython-38.pyc,, |
2464 | +charmhelpers/fetch/__pycache__/giturl.cpython-38.pyc,, |
2465 | +charmhelpers/fetch/__pycache__/snap.cpython-38.pyc,, |
2466 | +charmhelpers/fetch/__pycache__/ubuntu.cpython-38.pyc,, |
2467 | +charmhelpers/fetch/__pycache__/ubuntu_apt_pkg.cpython-38.pyc,, |
2468 | +charmhelpers/fetch/archiveurl.py,sha256=wcaorzMQdJ4uHGaMm8NDswjteSTztsdBC0U794EWo00,6095 |
2469 | +charmhelpers/fetch/bzrurl.py,sha256=yPz23U4uBQajXWsBoNwyWzNW-CTwBdOcI4FDnSQB0jI,2547 |
2470 | +charmhelpers/fetch/centos.py,sha256=fwFsxODb9mAMNfSiyNByy1hhWpwO75VjXUE9UW7Pduw,5656 |
2471 | +charmhelpers/fetch/giturl.py,sha256=1fNV446JDVUvionmQtuZyMc64v_9liizwfryJs5g0cE,2520 |
2472 | +charmhelpers/fetch/python/__init__.py,sha256=XatrYz38fPzslqxSdVKB4T-S8u69pdiirVtKA6syQD0,584 |
2473 | +charmhelpers/fetch/python/__pycache__/__init__.cpython-38.pyc,, |
2474 | +charmhelpers/fetch/python/__pycache__/debug.cpython-38.pyc,, |
2475 | +charmhelpers/fetch/python/__pycache__/packages.cpython-38.pyc,, |
2476 | +charmhelpers/fetch/python/__pycache__/rpdb.cpython-38.pyc,, |
2477 | +charmhelpers/fetch/python/__pycache__/version.cpython-38.pyc,, |
2478 | +charmhelpers/fetch/python/debug.py,sha256=O7KEdQBVc3d7AlS4qyVBnduiE_40SopYyhb0fNNeSEw,1595 |
2479 | +charmhelpers/fetch/python/packages.py,sha256=IWruxWDMaXYERRbYVShhB8cm60cgzWLzrtYCJAYJxKY,4755 |
2480 | +charmhelpers/fetch/python/rpdb.py,sha256=8bVkgR2A5IPMQVhiw3WZsPIUah3Si_3hicc5ytfPi-A,1910 |
2481 | +charmhelpers/fetch/python/version.py,sha256=PU-BN1jdVyNVygmDMEvPc7Ls1Wp43kTKyZvvD05KLuw,1062 |
2482 | +charmhelpers/fetch/snap.py,sha256=Ea8CcNP5F4NaZTSLxdrpqgZ7Bax1ROzpavSewMgVA3M,4295 |
2483 | +charmhelpers/fetch/ubuntu.py,sha256=Wf35QS3tWD0z34EXwG86qaW47x7QFY6bNVmlk30EI2A,38793 |
2484 | +charmhelpers/fetch/ubuntu_apt_pkg.py,sha256=Lss81SobnS4lJXE_0fUM2VJDNXXdu4sk6-igZdc53Co,10709 |
2485 | +charmhelpers/osplatform.py,sha256=vTOdFVPPbQITbesl_7EILJE-M0gd1iqI8vGoJx69eyg,1745 |
2486 | +charmhelpers/payload/__init__.py,sha256=BsLxY7GAAFKbd4-nMeZYhxXSQcf4HlaC4XAP06cNX6g,662 |
2487 | +charmhelpers/payload/__pycache__/__init__.cpython-38.pyc,, |
2488 | +charmhelpers/payload/__pycache__/archive.cpython-38.pyc,, |
2489 | +charmhelpers/payload/__pycache__/execd.cpython-38.pyc,, |
2490 | +charmhelpers/payload/archive.py,sha256=b5TPzQ-mWFoz2Xtw0GvDTcgnonT3_4XVRj2kcrESZtU,2156 |
2491 | +charmhelpers/payload/execd.py,sha256=64WyEjhxnBiFivmtSXGYmFauuSyUYkRimlr9Cyq6xAI,2248 |
2492 | +charmhelpers/version.py,sha256=BP5L3qROqNAJNf3RnyryDzfdiMGyLjm_6OPjMUgVf6w,58 |
2493 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/WHEEL b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/WHEEL |
2494 | new file mode 100644 |
2495 | index 0000000..b552003 |
2496 | --- /dev/null |
2497 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/WHEEL |
2498 | @@ -0,0 +1,5 @@ |
2499 | +Wheel-Version: 1.0 |
2500 | +Generator: bdist_wheel (0.34.2) |
2501 | +Root-Is-Purelib: true |
2502 | +Tag: py3-none-any |
2503 | + |
2504 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/pbr.json b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/pbr.json |
2505 | new file mode 100644 |
2506 | index 0000000..c585d02 |
2507 | --- /dev/null |
2508 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/pbr.json |
2509 | @@ -0,0 +1 @@ |
2510 | +{"git_version": "26efcd0d", "is_release": true} |
2511 | \ No newline at end of file |
2512 | diff --git a/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/top_level.txt b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/top_level.txt |
2513 | new file mode 100644 |
2514 | index 0000000..93cc907 |
2515 | --- /dev/null |
2516 | +++ b/charms/appstream-generator/venv/charmhelpers-0.20.23.dist-info/top_level.txt |
2517 | @@ -0,0 +1 @@ |
2518 | +charmhelpers |
2519 | diff --git a/charms/appstream-generator/venv/charmhelpers/__init__.py b/charms/appstream-generator/venv/charmhelpers/__init__.py |
2520 | new file mode 100644 |
2521 | index 0000000..1f57ed2 |
2522 | --- /dev/null |
2523 | +++ b/charms/appstream-generator/venv/charmhelpers/__init__.py |
2524 | @@ -0,0 +1,99 @@ |
2525 | +# Copyright 2014-2015 Canonical Limited. |
2526 | +# |
2527 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
2528 | +# you may not use this file except in compliance with the License. |
2529 | +# You may obtain a copy of the License at |
2530 | +# |
2531 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2532 | +# |
2533 | +# Unless required by applicable law or agreed to in writing, software |
2534 | +# distributed under the License is distributed on an "AS IS" BASIS, |
2535 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2536 | +# See the License for the specific language governing permissions and |
2537 | +# limitations under the License. |
2538 | + |
2539 | +# Bootstrap charm-helpers, installing its dependencies if necessary using |
2540 | +# only standard libraries. |
2541 | +from __future__ import print_function |
2542 | +from __future__ import absolute_import |
2543 | + |
2544 | +import functools |
2545 | +import inspect |
2546 | +import subprocess |
2547 | +import sys |
2548 | + |
2549 | +try: |
2550 | + import six # NOQA:F401 |
2551 | +except ImportError: |
2552 | + if sys.version_info.major == 2: |
2553 | + subprocess.check_call(['apt-get', 'install', '-y', 'python-six']) |
2554 | + else: |
2555 | + subprocess.check_call(['apt-get', 'install', '-y', 'python3-six']) |
2556 | + import six # NOQA:F401 |
2557 | + |
2558 | +try: |
2559 | + import yaml # NOQA:F401 |
2560 | +except ImportError: |
2561 | + if sys.version_info.major == 2: |
2562 | + subprocess.check_call(['apt-get', 'install', '-y', 'python-yaml']) |
2563 | + else: |
2564 | + subprocess.check_call(['apt-get', 'install', '-y', 'python3-yaml']) |
2565 | + import yaml # NOQA:F401 |
2566 | + |
2567 | + |
2568 | +# Holds a list of mapping of mangled function names that have been deprecated |
2569 | +# using the @deprecate decorator below. This is so that the warning is only |
2570 | +# printed once for each usage of the function. |
2571 | +__deprecated_functions = {} |
2572 | + |
2573 | + |
2574 | +def deprecate(warning, date=None, log=None): |
2575 | + """Add a deprecation warning the first time the function is used. |
2576 | + |
2577 | + The date which is a string in semi-ISO8660 format indicates the year-month |
2578 | + that the function is officially going to be removed. |
2579 | + |
2580 | + usage: |
2581 | + |
2582 | + @deprecate('use core/fetch/add_source() instead', '2017-04') |
2583 | + def contributed_add_source_thing(...): |
2584 | + ... |
2585 | + |
2586 | + And it then prints to the log ONCE that the function is deprecated. |
2587 | + The reason for passing the logging function (log) is so that hookenv.log |
2588 | + can be used for a charm if needed. |
2589 | + |
2590 | + :param warning: String to indicate what is to be used instead. |
2591 | + :param date: Optional string in YYYY-MM format to indicate when the |
2592 | + function will definitely (probably) be removed. |
2593 | + :param log: The log function to call in order to log. If None, logs to |
2594 | + stdout |
2595 | + """ |
2596 | + def wrap(f): |
2597 | + |
2598 | + @functools.wraps(f) |
2599 | + def wrapped_f(*args, **kwargs): |
2600 | + try: |
2601 | + module = inspect.getmodule(f) |
2602 | + file = inspect.getsourcefile(f) |
2603 | + lines = inspect.getsourcelines(f) |
2604 | + f_name = "{}-{}-{}..{}-{}".format( |
2605 | + module.__name__, file, lines[0], lines[-1], f.__name__) |
2606 | + except (IOError, TypeError): |
2607 | + # assume it was local, so just use the name of the function |
2608 | + f_name = f.__name__ |
2609 | + if f_name not in __deprecated_functions: |
2610 | + __deprecated_functions[f_name] = True |
2611 | + s = "DEPRECATION WARNING: Function {} is being removed".format( |
2612 | + f.__name__) |
2613 | + if date: |
2614 | + s = "{} on/around {}".format(s, date) |
2615 | + if warning: |
2616 | + s = "{} : {}".format(s, warning) |
2617 | + if log: |
2618 | + log(s) |
2619 | + else: |
2620 | + print(s) |
2621 | + return f(*args, **kwargs) |
2622 | + return wrapped_f |
2623 | + return wrap |
2624 | diff --git a/charms/appstream-generator/venv/charmhelpers/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/__pycache__/__init__.cpython-38.pyc |
2625 | new file mode 100644 |
2626 | index 0000000..baa5ef4 |
2627 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/__pycache__/__init__.cpython-38.pyc differ |
2628 | diff --git a/charms/appstream-generator/venv/charmhelpers/__pycache__/context.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/__pycache__/context.cpython-38.pyc |
2629 | new file mode 100644 |
2630 | index 0000000..3fc7d87 |
2631 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/__pycache__/context.cpython-38.pyc differ |
2632 | diff --git a/charms/appstream-generator/venv/charmhelpers/__pycache__/coordinator.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/__pycache__/coordinator.cpython-38.pyc |
2633 | new file mode 100644 |
2634 | index 0000000..6a3e413 |
2635 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/__pycache__/coordinator.cpython-38.pyc differ |
2636 | diff --git a/charms/appstream-generator/venv/charmhelpers/__pycache__/osplatform.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/__pycache__/osplatform.cpython-38.pyc |
2637 | new file mode 100644 |
2638 | index 0000000..0b5fdfe |
2639 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/__pycache__/osplatform.cpython-38.pyc differ |
2640 | diff --git a/charms/appstream-generator/venv/charmhelpers/__pycache__/version.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/__pycache__/version.cpython-38.pyc |
2641 | new file mode 100644 |
2642 | index 0000000..fad275c |
2643 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/__pycache__/version.cpython-38.pyc differ |
2644 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/README.rst b/charms/appstream-generator/venv/charmhelpers/cli/README.rst |
2645 | new file mode 100644 |
2646 | index 0000000..4c211ee |
2647 | --- /dev/null |
2648 | +++ b/charms/appstream-generator/venv/charmhelpers/cli/README.rst |
2649 | @@ -0,0 +1,57 @@ |
2650 | +========== |
2651 | +Commandant |
2652 | +========== |
2653 | + |
2654 | +----------------------------------------------------- |
2655 | +Automatic command-line interfaces to Python functions |
2656 | +----------------------------------------------------- |
2657 | + |
2658 | +One of the benefits of ``libvirt`` is the uniformity of the interface: the C API (as well as the bindings in other languages) is a set of functions that accept parameters that are nearly identical to the command-line arguments. If you run ``virsh``, you get an interactive command prompt that supports all of the same commands that your shell scripts use as ``virsh`` subcommands. |
2659 | + |
2660 | +Command execution and stdio manipulation is the greatest common factor across all development systems in the POSIX environment. By exposing your functions as commands that manipulate streams of text, you can make life easier for all the Ruby and Erlang and Go programmers in your life. |
2661 | + |
2662 | +Goals |
2663 | +===== |
2664 | + |
2665 | +* Single decorator to expose a function as a command. |
2666 | + * now two decorators - one "automatic" and one that allows authors to manipulate the arguments for fine-grained control.(MW) |
2667 | +* Automatic analysis of function signature through ``inspect.getargspec()`` on python 2 or ``inspect.getfullargspec()`` on python 3 |
2668 | +* Command argument parser built automatically with ``argparse`` |
2669 | +* Interactive interpreter loop object made with ``Cmd`` |
2670 | +* Options to output structured return value data via ``pprint``, ``yaml`` or ``json`` dumps. |
2671 | + |
2672 | +Other Important Features that need writing |
2673 | +------------------------------------------ |
2674 | + |
2675 | +* Help and Usage documentation can be automatically generated, but it will be important to let users override this behaviour |
2676 | +* The decorator should allow specifying further parameters to the parser's add_argument() calls, to specify types or to make arguments behave as boolean flags, etc. |
2677 | + - Filename arguments are important, as good practice is for functions to accept file objects as parameters. |
2678 | + - choices arguments help to limit bad input before the function is called |
2679 | +* Some automatic behaviour could make for better defaults, once the user can override them. |
2680 | + - We could automatically detect arguments that default to False or True, and automatically support --no-foo for foo=True. |
2681 | + - We could automatically support hyphens as alternates for underscores |
2682 | + - Arguments defaulting to sequence types could support the ``append`` action. |
2683 | + |
2684 | + |
2685 | +----------------------------------------------------- |
2686 | +Implementing subcommands |
2687 | +----------------------------------------------------- |
2688 | + |
2689 | +(WIP) |
2690 | + |
2691 | +So as to avoid dependencies on the cli module, subcommands should be defined separately from their implementations. The recommmendation would be to place definitions into separate modules near the implementations which they expose. |
2692 | + |
2693 | +Some examples:: |
2694 | + |
2695 | + from charmhelpers.cli import CommandLine |
2696 | + from charmhelpers.payload import execd |
2697 | + from charmhelpers.foo import bar |
2698 | + |
2699 | + cli = CommandLine() |
2700 | + |
2701 | + cli.subcommand(execd.execd_run) |
2702 | + |
2703 | + @cli.subcommand_builder("bar", help="Bar baz qux") |
2704 | + def barcmd_builder(subparser): |
2705 | + subparser.add_argument('argument1', help="yackety") |
2706 | + return bar |
2707 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/__init__.py b/charms/appstream-generator/venv/charmhelpers/cli/__init__.py |
2708 | new file mode 100644 |
2709 | index 0000000..74ea729 |
2710 | --- /dev/null |
2711 | +++ b/charms/appstream-generator/venv/charmhelpers/cli/__init__.py |
2712 | @@ -0,0 +1,196 @@ |
2713 | +# Copyright 2014-2015 Canonical Limited. |
2714 | +# |
2715 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
2716 | +# you may not use this file except in compliance with the License. |
2717 | +# You may obtain a copy of the License at |
2718 | +# |
2719 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2720 | +# |
2721 | +# Unless required by applicable law or agreed to in writing, software |
2722 | +# distributed under the License is distributed on an "AS IS" BASIS, |
2723 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2724 | +# See the License for the specific language governing permissions and |
2725 | +# limitations under the License. |
2726 | + |
2727 | +import inspect |
2728 | +import argparse |
2729 | +import sys |
2730 | + |
2731 | +import six |
2732 | +from six.moves import zip |
2733 | + |
2734 | +import charmhelpers.core.unitdata |
2735 | + |
2736 | + |
2737 | +class OutputFormatter(object): |
2738 | + def __init__(self, outfile=sys.stdout): |
2739 | + self.formats = ( |
2740 | + "raw", |
2741 | + "json", |
2742 | + "py", |
2743 | + "yaml", |
2744 | + "csv", |
2745 | + "tab", |
2746 | + ) |
2747 | + self.outfile = outfile |
2748 | + |
2749 | + def add_arguments(self, argument_parser): |
2750 | + formatgroup = argument_parser.add_mutually_exclusive_group() |
2751 | + choices = self.supported_formats |
2752 | + formatgroup.add_argument("--format", metavar='FMT', |
2753 | + help="Select output format for returned data, " |
2754 | + "where FMT is one of: {}".format(choices), |
2755 | + choices=choices, default='raw') |
2756 | + for fmt in self.formats: |
2757 | + fmtfunc = getattr(self, fmt) |
2758 | + formatgroup.add_argument("-{}".format(fmt[0]), |
2759 | + "--{}".format(fmt), action='store_const', |
2760 | + const=fmt, dest='format', |
2761 | + help=fmtfunc.__doc__) |
2762 | + |
2763 | + @property |
2764 | + def supported_formats(self): |
2765 | + return self.formats |
2766 | + |
2767 | + def raw(self, output): |
2768 | + """Output data as raw string (default)""" |
2769 | + if isinstance(output, (list, tuple)): |
2770 | + output = '\n'.join(map(str, output)) |
2771 | + self.outfile.write(str(output)) |
2772 | + |
2773 | + def py(self, output): |
2774 | + """Output data as a nicely-formatted python data structure""" |
2775 | + import pprint |
2776 | + pprint.pprint(output, stream=self.outfile) |
2777 | + |
2778 | + def json(self, output): |
2779 | + """Output data in JSON format""" |
2780 | + import json |
2781 | + json.dump(output, self.outfile) |
2782 | + |
2783 | + def yaml(self, output): |
2784 | + """Output data in YAML format""" |
2785 | + import yaml |
2786 | + yaml.safe_dump(output, self.outfile) |
2787 | + |
2788 | + def csv(self, output): |
2789 | + """Output data as excel-compatible CSV""" |
2790 | + import csv |
2791 | + csvwriter = csv.writer(self.outfile) |
2792 | + csvwriter.writerows(output) |
2793 | + |
2794 | + def tab(self, output): |
2795 | + """Output data in excel-compatible tab-delimited format""" |
2796 | + import csv |
2797 | + csvwriter = csv.writer(self.outfile, dialect=csv.excel_tab) |
2798 | + csvwriter.writerows(output) |
2799 | + |
2800 | + def format_output(self, output, fmt='raw'): |
2801 | + fmtfunc = getattr(self, fmt) |
2802 | + fmtfunc(output) |
2803 | + |
2804 | + |
2805 | +class CommandLine(object): |
2806 | + argument_parser = None |
2807 | + subparsers = None |
2808 | + formatter = None |
2809 | + exit_code = 0 |
2810 | + |
2811 | + def __init__(self): |
2812 | + if not self.argument_parser: |
2813 | + self.argument_parser = argparse.ArgumentParser(description='Perform common charm tasks') |
2814 | + if not self.formatter: |
2815 | + self.formatter = OutputFormatter() |
2816 | + self.formatter.add_arguments(self.argument_parser) |
2817 | + if not self.subparsers: |
2818 | + self.subparsers = self.argument_parser.add_subparsers(help='Commands') |
2819 | + |
2820 | + def subcommand(self, command_name=None): |
2821 | + """ |
2822 | + Decorate a function as a subcommand. Use its arguments as the |
2823 | + command-line arguments""" |
2824 | + def wrapper(decorated): |
2825 | + cmd_name = command_name or decorated.__name__ |
2826 | + subparser = self.subparsers.add_parser(cmd_name, |
2827 | + description=decorated.__doc__) |
2828 | + for args, kwargs in describe_arguments(decorated): |
2829 | + subparser.add_argument(*args, **kwargs) |
2830 | + subparser.set_defaults(func=decorated) |
2831 | + return decorated |
2832 | + return wrapper |
2833 | + |
2834 | + def test_command(self, decorated): |
2835 | + """ |
2836 | + Subcommand is a boolean test function, so bool return values should be |
2837 | + converted to a 0/1 exit code. |
2838 | + """ |
2839 | + decorated._cli_test_command = True |
2840 | + return decorated |
2841 | + |
2842 | + def no_output(self, decorated): |
2843 | + """ |
2844 | + Subcommand is not expected to return a value, so don't print a spurious None. |
2845 | + """ |
2846 | + decorated._cli_no_output = True |
2847 | + return decorated |
2848 | + |
2849 | + def subcommand_builder(self, command_name, description=None): |
2850 | + """ |
2851 | + Decorate a function that builds a subcommand. Builders should accept a |
2852 | + single argument (the subparser instance) and return the function to be |
2853 | + run as the command.""" |
2854 | + def wrapper(decorated): |
2855 | + subparser = self.subparsers.add_parser(command_name) |
2856 | + func = decorated(subparser) |
2857 | + subparser.set_defaults(func=func) |
2858 | + subparser.description = description or func.__doc__ |
2859 | + return wrapper |
2860 | + |
2861 | + def run(self): |
2862 | + "Run cli, processing arguments and executing subcommands." |
2863 | + arguments = self.argument_parser.parse_args() |
2864 | + if six.PY2: |
2865 | + argspec = inspect.getargspec(arguments.func) |
2866 | + else: |
2867 | + argspec = inspect.getfullargspec(arguments.func) |
2868 | + vargs = [] |
2869 | + for arg in argspec.args: |
2870 | + vargs.append(getattr(arguments, arg)) |
2871 | + if argspec.varargs: |
2872 | + vargs.extend(getattr(arguments, argspec.varargs)) |
2873 | + output = arguments.func(*vargs) |
2874 | + if getattr(arguments.func, '_cli_test_command', False): |
2875 | + self.exit_code = 0 if output else 1 |
2876 | + output = '' |
2877 | + if getattr(arguments.func, '_cli_no_output', False): |
2878 | + output = '' |
2879 | + self.formatter.format_output(output, arguments.format) |
2880 | + if charmhelpers.core.unitdata._KV: |
2881 | + charmhelpers.core.unitdata._KV.flush() |
2882 | + |
2883 | + |
2884 | +cmdline = CommandLine() |
2885 | + |
2886 | + |
2887 | +def describe_arguments(func): |
2888 | + """ |
2889 | + Analyze a function's signature and return a data structure suitable for |
2890 | + passing in as arguments to an argparse parser's add_argument() method.""" |
2891 | + |
2892 | + if six.PY2: |
2893 | + argspec = inspect.getargspec(func) |
2894 | + else: |
2895 | + argspec = inspect.getfullargspec(func) |
2896 | + # we should probably raise an exception somewhere if func includes **kwargs |
2897 | + if argspec.defaults: |
2898 | + positional_args = argspec.args[:-len(argspec.defaults)] |
2899 | + keyword_names = argspec.args[-len(argspec.defaults):] |
2900 | + for arg, default in zip(keyword_names, argspec.defaults): |
2901 | + yield ('--{}'.format(arg),), {'default': default} |
2902 | + else: |
2903 | + positional_args = argspec.args |
2904 | + |
2905 | + for arg in positional_args: |
2906 | + yield (arg,), {} |
2907 | + if argspec.varargs: |
2908 | + yield (argspec.varargs,), {'nargs': '*'} |
2909 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/__init__.cpython-38.pyc |
2910 | new file mode 100644 |
2911 | index 0000000..147dcce |
2912 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/__init__.cpython-38.pyc differ |
2913 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/benchmark.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/benchmark.cpython-38.pyc |
2914 | new file mode 100644 |
2915 | index 0000000..2f96b1e |
2916 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/benchmark.cpython-38.pyc differ |
2917 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/commands.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/commands.cpython-38.pyc |
2918 | new file mode 100644 |
2919 | index 0000000..dcb10a5 |
2920 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/commands.cpython-38.pyc differ |
2921 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/hookenv.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/hookenv.cpython-38.pyc |
2922 | new file mode 100644 |
2923 | index 0000000..47bbd05 |
2924 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/hookenv.cpython-38.pyc differ |
2925 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/host.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/host.cpython-38.pyc |
2926 | new file mode 100644 |
2927 | index 0000000..e2ed780 |
2928 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/host.cpython-38.pyc differ |
2929 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/unitdata.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/unitdata.cpython-38.pyc |
2930 | new file mode 100644 |
2931 | index 0000000..28911a1 |
2932 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/cli/__pycache__/unitdata.cpython-38.pyc differ |
2933 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/benchmark.py b/charms/appstream-generator/venv/charmhelpers/cli/benchmark.py |
2934 | new file mode 100644 |
2935 | index 0000000..303af14 |
2936 | --- /dev/null |
2937 | +++ b/charms/appstream-generator/venv/charmhelpers/cli/benchmark.py |
2938 | @@ -0,0 +1,34 @@ |
2939 | +# Copyright 2014-2015 Canonical Limited. |
2940 | +# |
2941 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
2942 | +# you may not use this file except in compliance with the License. |
2943 | +# You may obtain a copy of the License at |
2944 | +# |
2945 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2946 | +# |
2947 | +# Unless required by applicable law or agreed to in writing, software |
2948 | +# distributed under the License is distributed on an "AS IS" BASIS, |
2949 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2950 | +# See the License for the specific language governing permissions and |
2951 | +# limitations under the License. |
2952 | + |
2953 | +from . import cmdline |
2954 | +from charmhelpers.contrib.benchmark import Benchmark |
2955 | + |
2956 | + |
2957 | +@cmdline.subcommand(command_name='benchmark-start') |
2958 | +def start(): |
2959 | + Benchmark.start() |
2960 | + |
2961 | + |
2962 | +@cmdline.subcommand(command_name='benchmark-finish') |
2963 | +def finish(): |
2964 | + Benchmark.finish() |
2965 | + |
2966 | + |
2967 | +@cmdline.subcommand_builder('benchmark-composite', description="Set the benchmark composite score") |
2968 | +def service(subparser): |
2969 | + subparser.add_argument("value", help="The composite score.") |
2970 | + subparser.add_argument("units", help="The units the composite score represents, i.e., 'reads/sec'.") |
2971 | + subparser.add_argument("direction", help="'asc' if a lower score is better, 'desc' if a higher score is better.") |
2972 | + return Benchmark.set_composite_score |
2973 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/commands.py b/charms/appstream-generator/venv/charmhelpers/cli/commands.py |
2974 | new file mode 100644 |
2975 | index 0000000..b931056 |
2976 | --- /dev/null |
2977 | +++ b/charms/appstream-generator/venv/charmhelpers/cli/commands.py |
2978 | @@ -0,0 +1,30 @@ |
2979 | +# Copyright 2014-2015 Canonical Limited. |
2980 | +# |
2981 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
2982 | +# you may not use this file except in compliance with the License. |
2983 | +# You may obtain a copy of the License at |
2984 | +# |
2985 | +# http://www.apache.org/licenses/LICENSE-2.0 |
2986 | +# |
2987 | +# Unless required by applicable law or agreed to in writing, software |
2988 | +# distributed under the License is distributed on an "AS IS" BASIS, |
2989 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
2990 | +# See the License for the specific language governing permissions and |
2991 | +# limitations under the License. |
2992 | + |
2993 | +""" |
2994 | +This module loads sub-modules into the python runtime so they can be |
2995 | +discovered via the inspect module. In order to prevent flake8 from (rightfully) |
2996 | +telling us these are unused modules, throw a ' # noqa' at the end of each import |
2997 | +so that the warning is suppressed. |
2998 | +""" |
2999 | + |
3000 | +from . import CommandLine # noqa |
3001 | + |
3002 | +""" |
3003 | +Import the sub-modules which have decorated subcommands to register with chlp. |
3004 | +""" |
3005 | +from . import host # noqa |
3006 | +from . import benchmark # noqa |
3007 | +from . import unitdata # noqa |
3008 | +from . import hookenv # noqa |
3009 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/hookenv.py b/charms/appstream-generator/venv/charmhelpers/cli/hookenv.py |
3010 | new file mode 100644 |
3011 | index 0000000..bd72f44 |
3012 | --- /dev/null |
3013 | +++ b/charms/appstream-generator/venv/charmhelpers/cli/hookenv.py |
3014 | @@ -0,0 +1,21 @@ |
3015 | +# Copyright 2014-2015 Canonical Limited. |
3016 | +# |
3017 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3018 | +# you may not use this file except in compliance with the License. |
3019 | +# You may obtain a copy of the License at |
3020 | +# |
3021 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3022 | +# |
3023 | +# Unless required by applicable law or agreed to in writing, software |
3024 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3025 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3026 | +# See the License for the specific language governing permissions and |
3027 | +# limitations under the License. |
3028 | + |
3029 | +from . import cmdline |
3030 | +from charmhelpers.core import hookenv |
3031 | + |
3032 | + |
3033 | +cmdline.subcommand('relation-id')(hookenv.relation_id._wrapped) |
3034 | +cmdline.subcommand('service-name')(hookenv.service_name) |
3035 | +cmdline.subcommand('remote-service-name')(hookenv.remote_service_name._wrapped) |
3036 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/host.py b/charms/appstream-generator/venv/charmhelpers/cli/host.py |
3037 | new file mode 100644 |
3038 | index 0000000..4039684 |
3039 | --- /dev/null |
3040 | +++ b/charms/appstream-generator/venv/charmhelpers/cli/host.py |
3041 | @@ -0,0 +1,29 @@ |
3042 | +# Copyright 2014-2015 Canonical Limited. |
3043 | +# |
3044 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3045 | +# you may not use this file except in compliance with the License. |
3046 | +# You may obtain a copy of the License at |
3047 | +# |
3048 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3049 | +# |
3050 | +# Unless required by applicable law or agreed to in writing, software |
3051 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3052 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3053 | +# See the License for the specific language governing permissions and |
3054 | +# limitations under the License. |
3055 | + |
3056 | +from . import cmdline |
3057 | +from charmhelpers.core import host |
3058 | + |
3059 | + |
3060 | +@cmdline.subcommand() |
3061 | +def mounts(): |
3062 | + "List mounts" |
3063 | + return host.mounts() |
3064 | + |
3065 | + |
3066 | +@cmdline.subcommand_builder('service', description="Control system services") |
3067 | +def service(subparser): |
3068 | + subparser.add_argument("action", help="The action to perform (start, stop, etc...)") |
3069 | + subparser.add_argument("service_name", help="Name of the service to control") |
3070 | + return host.service |
3071 | diff --git a/charms/appstream-generator/venv/charmhelpers/cli/unitdata.py b/charms/appstream-generator/venv/charmhelpers/cli/unitdata.py |
3072 | new file mode 100644 |
3073 | index 0000000..acce846 |
3074 | --- /dev/null |
3075 | +++ b/charms/appstream-generator/venv/charmhelpers/cli/unitdata.py |
3076 | @@ -0,0 +1,46 @@ |
3077 | +# Copyright 2014-2015 Canonical Limited. |
3078 | +# |
3079 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3080 | +# you may not use this file except in compliance with the License. |
3081 | +# You may obtain a copy of the License at |
3082 | +# |
3083 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3084 | +# |
3085 | +# Unless required by applicable law or agreed to in writing, software |
3086 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3087 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3088 | +# See the License for the specific language governing permissions and |
3089 | +# limitations under the License. |
3090 | + |
3091 | +from . import cmdline |
3092 | +from charmhelpers.core import unitdata |
3093 | + |
3094 | + |
3095 | +@cmdline.subcommand_builder('unitdata', description="Store and retrieve data") |
3096 | +def unitdata_cmd(subparser): |
3097 | + nested = subparser.add_subparsers() |
3098 | + |
3099 | + get_cmd = nested.add_parser('get', help='Retrieve data') |
3100 | + get_cmd.add_argument('key', help='Key to retrieve the value of') |
3101 | + get_cmd.set_defaults(action='get', value=None) |
3102 | + |
3103 | + getrange_cmd = nested.add_parser('getrange', help='Retrieve multiple data') |
3104 | + getrange_cmd.add_argument('key', metavar='prefix', |
3105 | + help='Prefix of the keys to retrieve') |
3106 | + getrange_cmd.set_defaults(action='getrange', value=None) |
3107 | + |
3108 | + set_cmd = nested.add_parser('set', help='Store data') |
3109 | + set_cmd.add_argument('key', help='Key to set') |
3110 | + set_cmd.add_argument('value', help='Value to store') |
3111 | + set_cmd.set_defaults(action='set') |
3112 | + |
3113 | + def _unitdata_cmd(action, key, value): |
3114 | + if action == 'get': |
3115 | + return unitdata.kv().get(key) |
3116 | + elif action == 'getrange': |
3117 | + return unitdata.kv().getrange(key) |
3118 | + elif action == 'set': |
3119 | + unitdata.kv().set(key, value) |
3120 | + unitdata.kv().flush() |
3121 | + return '' |
3122 | + return _unitdata_cmd |
3123 | diff --git a/charms/appstream-generator/venv/charmhelpers/context.py b/charms/appstream-generator/venv/charmhelpers/context.py |
3124 | new file mode 100644 |
3125 | index 0000000..0186474 |
3126 | --- /dev/null |
3127 | +++ b/charms/appstream-generator/venv/charmhelpers/context.py |
3128 | @@ -0,0 +1,205 @@ |
3129 | +# Copyright 2015 Canonical Limited. |
3130 | +# |
3131 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3132 | +# you may not use this file except in compliance with the License. |
3133 | +# You may obtain a copy of the License at |
3134 | +# |
3135 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3136 | +# |
3137 | +# Unless required by applicable law or agreed to in writing, software |
3138 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3139 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3140 | +# See the License for the specific language governing permissions and |
3141 | +# limitations under the License. |
3142 | + |
3143 | +''' |
3144 | +A Pythonic API to interact with the charm hook environment. |
3145 | + |
3146 | +:author: Stuart Bishop <stuart.bishop@canonical.com> |
3147 | +''' |
3148 | + |
3149 | +import six |
3150 | + |
3151 | +from charmhelpers.core import hookenv |
3152 | + |
3153 | +from collections import OrderedDict |
3154 | +if six.PY3: |
3155 | + from collections import UserDict # pragma: nocover |
3156 | +else: |
3157 | + from UserDict import IterableUserDict as UserDict # pragma: nocover |
3158 | + |
3159 | + |
3160 | +class Relations(OrderedDict): |
3161 | + '''Mapping relation name -> relation id -> Relation. |
3162 | + |
3163 | + >>> rels = Relations() |
3164 | + >>> rels['sprog']['sprog:12']['client/6']['widget'] |
3165 | + 'remote widget' |
3166 | + >>> rels['sprog']['sprog:12'].local['widget'] = 'local widget' |
3167 | + >>> rels['sprog']['sprog:12'].local['widget'] |
3168 | + 'local widget' |
3169 | + >>> rels.peer.local['widget'] |
3170 | + 'local widget on the peer relation' |
3171 | + ''' |
3172 | + def __init__(self): |
3173 | + super(Relations, self).__init__() |
3174 | + for relname in sorted(hookenv.relation_types()): |
3175 | + self[relname] = OrderedDict() |
3176 | + relids = hookenv.relation_ids(relname) |
3177 | + relids.sort(key=lambda x: int(x.split(':', 1)[-1])) |
3178 | + for relid in relids: |
3179 | + self[relname][relid] = Relation(relid) |
3180 | + |
3181 | + @property |
3182 | + def peer(self): |
3183 | + peer_relid = hookenv.peer_relation_id() |
3184 | + for rels in self.values(): |
3185 | + if peer_relid in rels: |
3186 | + return rels[peer_relid] |
3187 | + |
3188 | + |
3189 | +class Relation(OrderedDict): |
3190 | + '''Mapping of unit -> remote RelationInfo for a relation. |
3191 | + |
3192 | + This is an OrderedDict mapping, ordered numerically by |
3193 | + by unit number. |
3194 | + |
3195 | + Also provides access to the local RelationInfo, and peer RelationInfo |
3196 | + instances by the 'local' and 'peers' attributes. |
3197 | + |
3198 | + >>> r = Relation('sprog:12') |
3199 | + >>> r.keys() |
3200 | + ['client/9', 'client/10'] # Ordered numerically |
3201 | + >>> r['client/10']['widget'] # A remote RelationInfo setting |
3202 | + 'remote widget' |
3203 | + >>> r.local['widget'] # The local RelationInfo setting |
3204 | + 'local widget' |
3205 | + ''' |
3206 | + relid = None # The relation id. |
3207 | + relname = None # The relation name (also known as relation type). |
3208 | + service = None # The remote service name, if known. |
3209 | + local = None # The local end's RelationInfo. |
3210 | + peers = None # Map of peer -> RelationInfo. None if no peer relation. |
3211 | + |
3212 | + def __init__(self, relid): |
3213 | + remote_units = hookenv.related_units(relid) |
3214 | + remote_units.sort(key=lambda u: int(u.split('/', 1)[-1])) |
3215 | + super(Relation, self).__init__((unit, RelationInfo(relid, unit)) |
3216 | + for unit in remote_units) |
3217 | + |
3218 | + self.relname = relid.split(':', 1)[0] |
3219 | + self.relid = relid |
3220 | + self.local = RelationInfo(relid, hookenv.local_unit()) |
3221 | + |
3222 | + for relinfo in self.values(): |
3223 | + self.service = relinfo.service |
3224 | + break |
3225 | + |
3226 | + # If we have peers, and they have joined both the provided peer |
3227 | + # relation and this relation, we can peek at their data too. |
3228 | + # This is useful for creating consensus without leadership. |
3229 | + peer_relid = hookenv.peer_relation_id() |
3230 | + if peer_relid and peer_relid != relid: |
3231 | + peers = hookenv.related_units(peer_relid) |
3232 | + if peers: |
3233 | + peers.sort(key=lambda u: int(u.split('/', 1)[-1])) |
3234 | + self.peers = OrderedDict((peer, RelationInfo(relid, peer)) |
3235 | + for peer in peers) |
3236 | + else: |
3237 | + self.peers = OrderedDict() |
3238 | + else: |
3239 | + self.peers = None |
3240 | + |
3241 | + def __str__(self): |
3242 | + return '{} ({})'.format(self.relid, self.service) |
3243 | + |
3244 | + |
3245 | +class RelationInfo(UserDict): |
3246 | + '''The bag of data at an end of a relation. |
3247 | + |
3248 | + Every unit participating in a relation has a single bag of |
3249 | + data associated with that relation. This is that bag. |
3250 | + |
3251 | + The bag of data for the local unit may be updated. Remote data |
3252 | + is immutable and will remain static for the duration of the hook. |
3253 | + |
3254 | + Changes made to the local units relation data only become visible |
3255 | + to other units after the hook completes successfully. If the hook |
3256 | + does not complete successfully, the changes are rolled back. |
3257 | + |
3258 | + Unlike standard Python mappings, setting an item to None is the |
3259 | + same as deleting it. |
3260 | + |
3261 | + >>> relinfo = RelationInfo('db:12') # Default is the local unit. |
3262 | + >>> relinfo['user'] = 'fred' |
3263 | + >>> relinfo['user'] |
3264 | + 'fred' |
3265 | + >>> relinfo['user'] = None |
3266 | + >>> 'fred' in relinfo |
3267 | + False |
3268 | + |
3269 | + This class wraps hookenv.relation_get and hookenv.relation_set. |
3270 | + All caching is left up to these two methods to avoid synchronization |
3271 | + issues. Data is only loaded on demand. |
3272 | + ''' |
3273 | + relid = None # The relation id. |
3274 | + relname = None # The relation name (also know as the relation type). |
3275 | + unit = None # The unit id. |
3276 | + number = None # The unit number (integer). |
3277 | + service = None # The service name. |
3278 | + |
3279 | + def __init__(self, relid, unit): |
3280 | + self.relname = relid.split(':', 1)[0] |
3281 | + self.relid = relid |
3282 | + self.unit = unit |
3283 | + self.service, num = self.unit.split('/', 1) |
3284 | + self.number = int(num) |
3285 | + |
3286 | + def __str__(self): |
3287 | + return '{} ({})'.format(self.relid, self.unit) |
3288 | + |
3289 | + @property |
3290 | + def data(self): |
3291 | + return hookenv.relation_get(rid=self.relid, unit=self.unit) |
3292 | + |
3293 | + def __setitem__(self, key, value): |
3294 | + if self.unit != hookenv.local_unit(): |
3295 | + raise TypeError('Attempting to set {} on remote unit {}' |
3296 | + ''.format(key, self.unit)) |
3297 | + if value is not None and not isinstance(value, six.string_types): |
3298 | + # We don't do implicit casting. This would cause simple |
3299 | + # types like integers to be read back as strings in subsequent |
3300 | + # hooks, and mutable types would require a lot of wrapping |
3301 | + # to ensure relation-set gets called when they are mutated. |
3302 | + raise ValueError('Only string values allowed') |
3303 | + hookenv.relation_set(self.relid, {key: value}) |
3304 | + |
3305 | + def __delitem__(self, key): |
3306 | + # Deleting a key and setting it to null is the same thing in |
3307 | + # Juju relations. |
3308 | + self[key] = None |
3309 | + |
3310 | + |
3311 | +class Leader(UserDict): |
3312 | + def __init__(self): |
3313 | + pass # Don't call superclass initializer, as it will nuke self.data |
3314 | + |
3315 | + @property |
3316 | + def data(self): |
3317 | + return hookenv.leader_get() |
3318 | + |
3319 | + def __setitem__(self, key, value): |
3320 | + if not hookenv.is_leader(): |
3321 | + raise TypeError('Not the leader. Cannot change leader settings.') |
3322 | + if value is not None and not isinstance(value, six.string_types): |
3323 | + # We don't do implicit casting. This would cause simple |
3324 | + # types like integers to be read back as strings in subsequent |
3325 | + # hooks, and mutable types would require a lot of wrapping |
3326 | + # to ensure leader-set gets called when they are mutated. |
3327 | + raise ValueError('Only string values allowed') |
3328 | + hookenv.leader_set({key: value}) |
3329 | + |
3330 | + def __delitem__(self, key): |
3331 | + # Deleting a key and setting it to null is the same thing in |
3332 | + # Juju leadership settings. |
3333 | + self[key] = None |
3334 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/__init__.py b/charms/appstream-generator/venv/charmhelpers/contrib/__init__.py |
3335 | new file mode 100644 |
3336 | index 0000000..d7567b8 |
3337 | --- /dev/null |
3338 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/__init__.py |
3339 | @@ -0,0 +1,13 @@ |
3340 | +# Copyright 2014-2015 Canonical Limited. |
3341 | +# |
3342 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3343 | +# you may not use this file except in compliance with the License. |
3344 | +# You may obtain a copy of the License at |
3345 | +# |
3346 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3347 | +# |
3348 | +# Unless required by applicable law or agreed to in writing, software |
3349 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3350 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3351 | +# See the License for the specific language governing permissions and |
3352 | +# limitations under the License. |
3353 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/__pycache__/__init__.cpython-38.pyc |
3354 | new file mode 100644 |
3355 | index 0000000..ca347f8 |
3356 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/__pycache__/__init__.cpython-38.pyc differ |
3357 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/__pycache__/python.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/__pycache__/python.cpython-38.pyc |
3358 | new file mode 100644 |
3359 | index 0000000..43765f3 |
3360 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/__pycache__/python.cpython-38.pyc differ |
3361 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/ansible/__init__.py b/charms/appstream-generator/venv/charmhelpers/contrib/ansible/__init__.py |
3362 | new file mode 100644 |
3363 | index 0000000..8a56972 |
3364 | --- /dev/null |
3365 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/ansible/__init__.py |
3366 | @@ -0,0 +1,306 @@ |
3367 | +# Copyright 2014-2015 Canonical Limited. |
3368 | +# |
3369 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3370 | +# you may not use this file except in compliance with the License. |
3371 | +# You may obtain a copy of the License at |
3372 | +# |
3373 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3374 | +# |
3375 | +# Unless required by applicable law or agreed to in writing, software |
3376 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3377 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3378 | +# See the License for the specific language governing permissions and |
3379 | +# limitations under the License. |
3380 | + |
3381 | +# Copyright 2013 Canonical Ltd. |
3382 | +# |
3383 | +# Authors: |
3384 | +# Charm Helpers Developers <juju@lists.ubuntu.com> |
3385 | +""" |
3386 | +The ansible package enables you to easily use the configuration management |
3387 | +tool `Ansible`_ to setup and configure your charm. All of your charm |
3388 | +configuration options and relation-data are available as regular Ansible |
3389 | +variables which can be used in your playbooks and templates. |
3390 | + |
3391 | +.. _Ansible: https://www.ansible.com/ |
3392 | + |
3393 | +Usage |
3394 | +===== |
3395 | + |
3396 | +Here is an example directory structure for a charm to get you started:: |
3397 | + |
3398 | + charm-ansible-example/ |
3399 | + |-- ansible |
3400 | + | |-- playbook.yaml |
3401 | + | `-- templates |
3402 | + | `-- example.j2 |
3403 | + |-- config.yaml |
3404 | + |-- copyright |
3405 | + |-- icon.svg |
3406 | + |-- layer.yaml |
3407 | + |-- metadata.yaml |
3408 | + |-- reactive |
3409 | + | `-- example.py |
3410 | + |-- README.md |
3411 | + |
3412 | +Running a playbook called ``playbook.yaml`` when the ``install`` hook is run |
3413 | +can be as simple as:: |
3414 | + |
3415 | + from charmhelpers.contrib import ansible |
3416 | + from charms.reactive import hook |
3417 | + |
3418 | + @hook('install') |
3419 | + def install(): |
3420 | + ansible.install_ansible_support() |
3421 | + ansible.apply_playbook('ansible/playbook.yaml') |
3422 | + |
3423 | +Here is an example playbook that uses the ``template`` module to template the |
3424 | +file ``example.j2`` to the charm host and then uses the ``debug`` module to |
3425 | +print out all the host and Juju variables that you can use in your playbooks. |
3426 | +Note that you must target ``localhost`` as the playbook is run locally on the |
3427 | +charm host:: |
3428 | + |
3429 | + --- |
3430 | + - hosts: localhost |
3431 | + tasks: |
3432 | + - name: Template a file |
3433 | + template: |
3434 | + src: templates/example.j2 |
3435 | + dest: /tmp/example.j2 |
3436 | + |
3437 | + - name: Print all variables available to Ansible |
3438 | + debug: |
3439 | + var: vars |
3440 | + |
3441 | +Read more online about `playbooks`_ and standard Ansible `modules`_. |
3442 | + |
3443 | +.. _playbooks: https://docs.ansible.com/ansible/latest/user_guide/playbooks.html |
3444 | +.. _modules: https://docs.ansible.com/ansible/latest/user_guide/modules.html |
3445 | + |
3446 | +A further feature of the Ansible hooks is to provide a light weight "action" |
3447 | +scripting tool. This is a decorator that you apply to a function, and that |
3448 | +function can now receive cli args, and can pass extra args to the playbook:: |
3449 | + |
3450 | + @hooks.action() |
3451 | + def some_action(amount, force="False"): |
3452 | + "Usage: some-action AMOUNT [force=True]" # <-- shown on error |
3453 | + # process the arguments |
3454 | + # do some calls |
3455 | + # return extra-vars to be passed to ansible-playbook |
3456 | + return { |
3457 | + 'amount': int(amount), |
3458 | + 'type': force, |
3459 | + } |
3460 | + |
3461 | +You can now create a symlink to hooks.py that can be invoked like a hook, but |
3462 | +with cli params:: |
3463 | + |
3464 | + # link actions/some-action to hooks/hooks.py |
3465 | + |
3466 | + actions/some-action amount=10 force=true |
3467 | + |
3468 | +Install Ansible via pip |
3469 | +======================= |
3470 | + |
3471 | +If you want to install a specific version of Ansible via pip instead of |
3472 | +``install_ansible_support`` which uses APT, consider using the layer options |
3473 | +of `layer-basic`_ to install Ansible in a virtualenv:: |
3474 | + |
3475 | + options: |
3476 | + basic: |
3477 | + python_packages: ['ansible==2.9.0'] |
3478 | + include_system_packages: true |
3479 | + use_venv: true |
3480 | + |
3481 | +.. _layer-basic: https://charmsreactive.readthedocs.io/en/latest/layer-basic.html#layer-configuration |
3482 | + |
3483 | +""" |
3484 | +import os |
3485 | +import json |
3486 | +import stat |
3487 | +import subprocess |
3488 | +import functools |
3489 | + |
3490 | +import charmhelpers.contrib.templating.contexts |
3491 | +import charmhelpers.core.host |
3492 | +import charmhelpers.core.hookenv |
3493 | +import charmhelpers.fetch |
3494 | + |
3495 | + |
3496 | +charm_dir = os.environ.get('CHARM_DIR', '') |
3497 | +ansible_hosts_path = '/etc/ansible/hosts' |
3498 | +# Ansible will automatically include any vars in the following |
3499 | +# file in its inventory when run locally. |
3500 | +ansible_vars_path = '/etc/ansible/host_vars/localhost' |
3501 | + |
3502 | + |
3503 | +def install_ansible_support(from_ppa=True, ppa_location='ppa:ansible/ansible'): |
3504 | + """Installs Ansible via APT. |
3505 | + |
3506 | + By default this installs Ansible from the `PPA`_ linked from |
3507 | + the Ansible `website`_ or from a PPA set in ``ppa_location``. |
3508 | + |
3509 | + .. _PPA: https://launchpad.net/~ansible/+archive/ubuntu/ansible |
3510 | + .. _website: http://docs.ansible.com/intro_installation.html#latest-releases-via-apt-ubuntu |
3511 | + |
3512 | + If ``from_ppa`` is ``False``, then Ansible will be installed from |
3513 | + Ubuntu's Universe repositories. |
3514 | + """ |
3515 | + if from_ppa: |
3516 | + charmhelpers.fetch.add_source(ppa_location) |
3517 | + charmhelpers.fetch.apt_update(fatal=True) |
3518 | + charmhelpers.fetch.apt_install('ansible') |
3519 | + with open(ansible_hosts_path, 'w+') as hosts_file: |
3520 | + hosts_file.write('localhost ansible_connection=local ansible_remote_tmp=/root/.ansible/tmp') |
3521 | + |
3522 | + |
3523 | +def apply_playbook(playbook, tags=None, extra_vars=None): |
3524 | + """Run a playbook. |
3525 | + |
3526 | + This helper runs a playbook with juju state variables as context, |
3527 | + therefore variables set in application config can be used directly. |
3528 | + List of tags (--tags) and dictionary with extra_vars (--extra-vars) |
3529 | + can be passed as additional parameters. |
3530 | + |
3531 | + Read more about playbook `_variables`_ online. |
3532 | + |
3533 | + .. _variables: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html |
3534 | + |
3535 | + Example:: |
3536 | + |
3537 | + # Run ansible/playbook.yaml with tag install and pass extra |
3538 | + # variables var_a and var_b |
3539 | + apply_playbook( |
3540 | + playbook='ansible/playbook.yaml', |
3541 | + tags=['install'], |
3542 | + extra_vars={'var_a': 'val_a', 'var_b': 'val_b'} |
3543 | + ) |
3544 | + |
3545 | + # Run ansible/playbook.yaml with tag config and extra variable nested, |
3546 | + # which is passed as json and can be used as dictionary in playbook |
3547 | + apply_playbook( |
3548 | + playbook='ansible/playbook.yaml', |
3549 | + tags=['config'], |
3550 | + extra_vars={'nested': {'a': 'value1', 'b': 'value2'}} |
3551 | + ) |
3552 | + |
3553 | + # Custom config file can be passed within extra_vars |
3554 | + apply_playbook( |
3555 | + playbook='ansible/playbook.yaml', |
3556 | + extra_vars="@some_file.json" |
3557 | + ) |
3558 | + |
3559 | + """ |
3560 | + tags = tags or [] |
3561 | + tags = ",".join(tags) |
3562 | + charmhelpers.contrib.templating.contexts.juju_state_to_yaml( |
3563 | + ansible_vars_path, namespace_separator='__', |
3564 | + allow_hyphens_in_keys=False, mode=(stat.S_IRUSR | stat.S_IWUSR)) |
3565 | + |
3566 | + # we want ansible's log output to be unbuffered |
3567 | + env = os.environ.copy() |
3568 | + proxy_settings = charmhelpers.core.hookenv.env_proxy_settings() |
3569 | + if proxy_settings: |
3570 | + env.update(proxy_settings) |
3571 | + env['PYTHONUNBUFFERED'] = "1" |
3572 | + call = [ |
3573 | + 'ansible-playbook', |
3574 | + '-c', |
3575 | + 'local', |
3576 | + playbook, |
3577 | + ] |
3578 | + if tags: |
3579 | + call.extend(['--tags', '{}'.format(tags)]) |
3580 | + if extra_vars: |
3581 | + call.extend(['--extra-vars', json.dumps(extra_vars)]) |
3582 | + subprocess.check_call(call, env=env) |
3583 | + |
3584 | + |
3585 | +class AnsibleHooks(charmhelpers.core.hookenv.Hooks): |
3586 | + """Run a playbook with the hook-name as the tag. |
3587 | + |
3588 | + This helper builds on the standard hookenv.Hooks helper, |
3589 | + but additionally runs the playbook with the hook-name specified |
3590 | + using --tags (ie. running all the tasks tagged with the hook-name). |
3591 | + |
3592 | + Example:: |
3593 | + |
3594 | + hooks = AnsibleHooks(playbook_path='ansible/my_machine_state.yaml') |
3595 | + |
3596 | + # All the tasks within my_machine_state.yaml tagged with 'install' |
3597 | + # will be run automatically after do_custom_work() |
3598 | + @hooks.hook() |
3599 | + def install(): |
3600 | + do_custom_work() |
3601 | + |
3602 | + # For most of your hooks, you won't need to do anything other |
3603 | + # than run the tagged tasks for the hook: |
3604 | + @hooks.hook('config-changed', 'start', 'stop') |
3605 | + def just_use_playbook(): |
3606 | + pass |
3607 | + |
3608 | + # As a convenience, you can avoid the above noop function by specifying |
3609 | + # the hooks which are handled by ansible-only and they'll be registered |
3610 | + # for you: |
3611 | + # hooks = AnsibleHooks( |
3612 | + # 'ansible/my_machine_state.yaml', |
3613 | + # default_hooks=['config-changed', 'start', 'stop']) |
3614 | + |
3615 | + if __name__ == "__main__": |
3616 | + # execute a hook based on the name the program is called by |
3617 | + hooks.execute(sys.argv) |
3618 | + """ |
3619 | + |
3620 | + def __init__(self, playbook_path, default_hooks=None): |
3621 | + """Register any hooks handled by ansible.""" |
3622 | + super(AnsibleHooks, self).__init__() |
3623 | + |
3624 | + self._actions = {} |
3625 | + self.playbook_path = playbook_path |
3626 | + |
3627 | + default_hooks = default_hooks or [] |
3628 | + |
3629 | + def noop(*args, **kwargs): |
3630 | + pass |
3631 | + |
3632 | + for hook in default_hooks: |
3633 | + self.register(hook, noop) |
3634 | + |
3635 | + def register_action(self, name, function): |
3636 | + """Register a hook""" |
3637 | + self._actions[name] = function |
3638 | + |
3639 | + def execute(self, args): |
3640 | + """Execute the hook followed by the playbook using the hook as tag.""" |
3641 | + hook_name = os.path.basename(args[0]) |
3642 | + extra_vars = None |
3643 | + if hook_name in self._actions: |
3644 | + extra_vars = self._actions[hook_name](args[1:]) |
3645 | + else: |
3646 | + super(AnsibleHooks, self).execute(args) |
3647 | + |
3648 | + charmhelpers.contrib.ansible.apply_playbook( |
3649 | + self.playbook_path, tags=[hook_name], extra_vars=extra_vars) |
3650 | + |
3651 | + def action(self, *action_names): |
3652 | + """Decorator, registering them as actions""" |
3653 | + def action_wrapper(decorated): |
3654 | + |
3655 | + @functools.wraps(decorated) |
3656 | + def wrapper(argv): |
3657 | + kwargs = dict(arg.split('=') for arg in argv) |
3658 | + try: |
3659 | + return decorated(**kwargs) |
3660 | + except TypeError as e: |
3661 | + if decorated.__doc__: |
3662 | + e.args += (decorated.__doc__,) |
3663 | + raise |
3664 | + |
3665 | + self.register_action(decorated.__name__, wrapper) |
3666 | + if '_' in decorated.__name__: |
3667 | + self.register_action( |
3668 | + decorated.__name__.replace('_', '-'), wrapper) |
3669 | + |
3670 | + return wrapper |
3671 | + |
3672 | + return action_wrapper |
3673 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/ansible/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/ansible/__pycache__/__init__.cpython-38.pyc |
3674 | new file mode 100644 |
3675 | index 0000000..c21f6a9 |
3676 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/ansible/__pycache__/__init__.cpython-38.pyc differ |
3677 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/benchmark/__init__.py b/charms/appstream-generator/venv/charmhelpers/contrib/benchmark/__init__.py |
3678 | new file mode 100644 |
3679 | index 0000000..c35f7fe |
3680 | --- /dev/null |
3681 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/benchmark/__init__.py |
3682 | @@ -0,0 +1,124 @@ |
3683 | +# Copyright 2014-2015 Canonical Limited. |
3684 | +# |
3685 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3686 | +# you may not use this file except in compliance with the License. |
3687 | +# You may obtain a copy of the License at |
3688 | +# |
3689 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3690 | +# |
3691 | +# Unless required by applicable law or agreed to in writing, software |
3692 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3693 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3694 | +# See the License for the specific language governing permissions and |
3695 | +# limitations under the License. |
3696 | + |
3697 | +import subprocess |
3698 | +import time |
3699 | +import os |
3700 | +from distutils.spawn import find_executable |
3701 | + |
3702 | +from charmhelpers.core.hookenv import ( |
3703 | + in_relation_hook, |
3704 | + relation_ids, |
3705 | + relation_set, |
3706 | + relation_get, |
3707 | +) |
3708 | + |
3709 | + |
3710 | +def action_set(key, val): |
3711 | + if find_executable('action-set'): |
3712 | + action_cmd = ['action-set'] |
3713 | + |
3714 | + if isinstance(val, dict): |
3715 | + for k, v in iter(val.items()): |
3716 | + action_set('%s.%s' % (key, k), v) |
3717 | + return True |
3718 | + |
3719 | + action_cmd.append('%s=%s' % (key, val)) |
3720 | + subprocess.check_call(action_cmd) |
3721 | + return True |
3722 | + return False |
3723 | + |
3724 | + |
3725 | +class Benchmark(): |
3726 | + """ |
3727 | + Helper class for the `benchmark` interface. |
3728 | + |
3729 | + :param list actions: Define the actions that are also benchmarks |
3730 | + |
3731 | + From inside the benchmark-relation-changed hook, you would |
3732 | + Benchmark(['memory', 'cpu', 'disk', 'smoke', 'custom']) |
3733 | + |
3734 | + Examples: |
3735 | + |
3736 | + siege = Benchmark(['siege']) |
3737 | + siege.start() |
3738 | + [... run siege ...] |
3739 | + # The higher the score, the better the benchmark |
3740 | + siege.set_composite_score(16.70, 'trans/sec', 'desc') |
3741 | + siege.finish() |
3742 | + |
3743 | + |
3744 | + """ |
3745 | + |
3746 | + BENCHMARK_CONF = '/etc/benchmark.conf' # Replaced in testing |
3747 | + |
3748 | + required_keys = [ |
3749 | + 'hostname', |
3750 | + 'port', |
3751 | + 'graphite_port', |
3752 | + 'graphite_endpoint', |
3753 | + 'api_port' |
3754 | + ] |
3755 | + |
3756 | + def __init__(self, benchmarks=None): |
3757 | + if in_relation_hook(): |
3758 | + if benchmarks is not None: |
3759 | + for rid in sorted(relation_ids('benchmark')): |
3760 | + relation_set(relation_id=rid, relation_settings={ |
3761 | + 'benchmarks': ",".join(benchmarks) |
3762 | + }) |
3763 | + |
3764 | + # Check the relation data |
3765 | + config = {} |
3766 | + for key in self.required_keys: |
3767 | + val = relation_get(key) |
3768 | + if val is not None: |
3769 | + config[key] = val |
3770 | + else: |
3771 | + # We don't have all of the required keys |
3772 | + config = {} |
3773 | + break |
3774 | + |
3775 | + if len(config): |
3776 | + with open(self.BENCHMARK_CONF, 'w') as f: |
3777 | + for key, val in iter(config.items()): |
3778 | + f.write("%s=%s\n" % (key, val)) |
3779 | + |
3780 | + @staticmethod |
3781 | + def start(): |
3782 | + action_set('meta.start', time.strftime('%Y-%m-%dT%H:%M:%SZ')) |
3783 | + |
3784 | + """ |
3785 | + If the collectd charm is also installed, tell it to send a snapshot |
3786 | + of the current profile data. |
3787 | + """ |
3788 | + COLLECT_PROFILE_DATA = '/usr/local/bin/collect-profile-data' |
3789 | + if os.path.exists(COLLECT_PROFILE_DATA): |
3790 | + subprocess.check_output([COLLECT_PROFILE_DATA]) |
3791 | + |
3792 | + @staticmethod |
3793 | + def finish(): |
3794 | + action_set('meta.stop', time.strftime('%Y-%m-%dT%H:%M:%SZ')) |
3795 | + |
3796 | + @staticmethod |
3797 | + def set_composite_score(value, units, direction='asc'): |
3798 | + """ |
3799 | + Set the composite score for a benchmark run. This is a single number |
3800 | + representative of the benchmark results. This could be the most |
3801 | + important metric, or an amalgamation of metric scores. |
3802 | + """ |
3803 | + return action_set( |
3804 | + "meta.composite", |
3805 | + {'value': value, 'units': units, 'direction': direction} |
3806 | + ) |
3807 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/benchmark/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/benchmark/__pycache__/__init__.cpython-38.pyc |
3808 | new file mode 100644 |
3809 | index 0000000..b5d3978 |
3810 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/benchmark/__pycache__/__init__.cpython-38.pyc differ |
3811 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/IMPORT b/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/IMPORT |
3812 | new file mode 100644 |
3813 | index 0000000..d41cb04 |
3814 | --- /dev/null |
3815 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/IMPORT |
3816 | @@ -0,0 +1,4 @@ |
3817 | +Source lp:charm-tools/trunk |
3818 | + |
3819 | +charm-tools/helpers/python/charmhelpers/__init__.py -> charmhelpers/charmhelpers/contrib/charmhelpers/__init__.py |
3820 | +charm-tools/helpers/python/charmhelpers/tests/test_charmhelpers.py -> charmhelpers/tests/contrib/charmhelpers/test_charmhelpers.py |
3821 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/__init__.py b/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/__init__.py |
3822 | new file mode 100644 |
3823 | index 0000000..ed63e81 |
3824 | --- /dev/null |
3825 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/__init__.py |
3826 | @@ -0,0 +1,203 @@ |
3827 | +# Copyright 2014-2015 Canonical Limited. |
3828 | +# |
3829 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
3830 | +# you may not use this file except in compliance with the License. |
3831 | +# You may obtain a copy of the License at |
3832 | +# |
3833 | +# http://www.apache.org/licenses/LICENSE-2.0 |
3834 | +# |
3835 | +# Unless required by applicable law or agreed to in writing, software |
3836 | +# distributed under the License is distributed on an "AS IS" BASIS, |
3837 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
3838 | +# See the License for the specific language governing permissions and |
3839 | +# limitations under the License. |
3840 | + |
3841 | +import warnings |
3842 | +warnings.warn("contrib.charmhelpers is deprecated", DeprecationWarning) # noqa |
3843 | + |
3844 | +import operator |
3845 | +import tempfile |
3846 | +import time |
3847 | +import yaml |
3848 | +import subprocess |
3849 | + |
3850 | +import six |
3851 | +if six.PY3: |
3852 | + from urllib.request import urlopen |
3853 | + from urllib.error import (HTTPError, URLError) |
3854 | +else: |
3855 | + from urllib2 import (urlopen, HTTPError, URLError) |
3856 | + |
3857 | +"""Helper functions for writing Juju charms in Python.""" |
3858 | + |
3859 | +__metaclass__ = type |
3860 | +__all__ = [ |
3861 | + # 'get_config', # core.hookenv.config() |
3862 | + # 'log', # core.hookenv.log() |
3863 | + # 'log_entry', # core.hookenv.log() |
3864 | + # 'log_exit', # core.hookenv.log() |
3865 | + # 'relation_get', # core.hookenv.relation_get() |
3866 | + # 'relation_set', # core.hookenv.relation_set() |
3867 | + # 'relation_ids', # core.hookenv.relation_ids() |
3868 | + # 'relation_list', # core.hookenv.relation_units() |
3869 | + # 'config_get', # core.hookenv.config() |
3870 | + # 'unit_get', # core.hookenv.unit_get() |
3871 | + # 'open_port', # core.hookenv.open_port() |
3872 | + # 'close_port', # core.hookenv.close_port() |
3873 | + # 'service_control', # core.host.service() |
3874 | + 'unit_info', # client-side, NOT IMPLEMENTED |
3875 | + 'wait_for_machine', # client-side, NOT IMPLEMENTED |
3876 | + 'wait_for_page_contents', # client-side, NOT IMPLEMENTED |
3877 | + 'wait_for_relation', # client-side, NOT IMPLEMENTED |
3878 | + 'wait_for_unit', # client-side, NOT IMPLEMENTED |
3879 | +] |
3880 | + |
3881 | + |
3882 | +SLEEP_AMOUNT = 0.1 |
3883 | + |
3884 | + |
3885 | +# We create a juju_status Command here because it makes testing much, |
3886 | +# much easier. |
3887 | +def juju_status(): |
3888 | + subprocess.check_call(['juju', 'status']) |
3889 | + |
3890 | +# re-implemented as charmhelpers.fetch.configure_sources() |
3891 | +# def configure_source(update=False): |
3892 | +# source = config_get('source') |
3893 | +# if ((source.startswith('ppa:') or |
3894 | +# source.startswith('cloud:') or |
3895 | +# source.startswith('http:'))): |
3896 | +# run('add-apt-repository', source) |
3897 | +# if source.startswith("http:"): |
3898 | +# run('apt-key', 'import', config_get('key')) |
3899 | +# if update: |
3900 | +# run('apt-get', 'update') |
3901 | + |
3902 | + |
3903 | +# DEPRECATED: client-side only |
3904 | +def make_charm_config_file(charm_config): |
3905 | + charm_config_file = tempfile.NamedTemporaryFile(mode='w+') |
3906 | + charm_config_file.write(yaml.dump(charm_config)) |
3907 | + charm_config_file.flush() |
3908 | + # The NamedTemporaryFile instance is returned instead of just the name |
3909 | + # because we want to take advantage of garbage collection-triggered |
3910 | + # deletion of the temp file when it goes out of scope in the caller. |
3911 | + return charm_config_file |
3912 | + |
3913 | + |
3914 | +# DEPRECATED: client-side only |
3915 | +def unit_info(service_name, item_name, data=None, unit=None): |
3916 | + if data is None: |
3917 | + data = yaml.safe_load(juju_status()) |
3918 | + service = data['services'].get(service_name) |
3919 | + if service is None: |
3920 | + # XXX 2012-02-08 gmb: |
3921 | + # This allows us to cope with the race condition that we |
3922 | + # have between deploying a service and having it come up in |
3923 | + # `juju status`. We could probably do with cleaning it up so |
3924 | + # that it fails a bit more noisily after a while. |
3925 | + return '' |
3926 | + units = service['units'] |
3927 | + if unit is not None: |
3928 | + item = units[unit][item_name] |
3929 | + else: |
3930 | + # It might seem odd to sort the units here, but we do it to |
3931 | + # ensure that when no unit is specified, the first unit for the |
3932 | + # service (or at least the one with the lowest number) is the |
3933 | + # one whose data gets returned. |
3934 | + sorted_unit_names = sorted(units.keys()) |
3935 | + item = units[sorted_unit_names[0]][item_name] |
3936 | + return item |
3937 | + |
3938 | + |
3939 | +# DEPRECATED: client-side only |
3940 | +def get_machine_data(): |
3941 | + return yaml.safe_load(juju_status())['machines'] |
3942 | + |
3943 | + |
3944 | +# DEPRECATED: client-side only |
3945 | +def wait_for_machine(num_machines=1, timeout=300): |
3946 | + """Wait `timeout` seconds for `num_machines` machines to come up. |
3947 | + |
3948 | + This wait_for... function can be called by other wait_for functions |
3949 | + whose timeouts might be too short in situations where only a bare |
3950 | + Juju setup has been bootstrapped. |
3951 | + |
3952 | + :return: A tuple of (num_machines, time_taken). This is used for |
3953 | + testing. |
3954 | + """ |
3955 | + # You may think this is a hack, and you'd be right. The easiest way |
3956 | + # to tell what environment we're working in (LXC vs EC2) is to check |
3957 | + # the dns-name of the first machine. If it's localhost we're in LXC |
3958 | + # and we can just return here. |
3959 | + if get_machine_data()[0]['dns-name'] == 'localhost': |
3960 | + return 1, 0 |
3961 | + start_time = time.time() |
3962 | + while True: |
3963 | + # Drop the first machine, since it's the Zookeeper and that's |
3964 | + # not a machine that we need to wait for. This will only work |
3965 | + # for EC2 environments, which is why we return early above if |
3966 | + # we're in LXC. |
3967 | + machine_data = get_machine_data() |
3968 | + non_zookeeper_machines = [ |
3969 | + machine_data[key] for key in list(machine_data.keys())[1:]] |
3970 | + if len(non_zookeeper_machines) >= num_machines: |
3971 | + all_machines_running = True |
3972 | + for machine in non_zookeeper_machines: |
3973 | + if machine.get('instance-state') != 'running': |
3974 | + all_machines_running = False |
3975 | + break |
3976 | + if all_machines_running: |
3977 | + break |
3978 | + if time.time() - start_time >= timeout: |
3979 | + raise RuntimeError('timeout waiting for service to start') |
3980 | + time.sleep(SLEEP_AMOUNT) |
3981 | + return num_machines, time.time() - start_time |
3982 | + |
3983 | + |
3984 | +# DEPRECATED: client-side only |
3985 | +def wait_for_unit(service_name, timeout=480): |
3986 | + """Wait `timeout` seconds for a given service name to come up.""" |
3987 | + wait_for_machine(num_machines=1) |
3988 | + start_time = time.time() |
3989 | + while True: |
3990 | + state = unit_info(service_name, 'agent-state') |
3991 | + if 'error' in state or state == 'started': |
3992 | + break |
3993 | + if time.time() - start_time >= timeout: |
3994 | + raise RuntimeError('timeout waiting for service to start') |
3995 | + time.sleep(SLEEP_AMOUNT) |
3996 | + if state != 'started': |
3997 | + raise RuntimeError('unit did not start, agent-state: ' + state) |
3998 | + |
3999 | + |
4000 | +# DEPRECATED: client-side only |
4001 | +def wait_for_relation(service_name, relation_name, timeout=120): |
4002 | + """Wait `timeout` seconds for a given relation to come up.""" |
4003 | + start_time = time.time() |
4004 | + while True: |
4005 | + relation = unit_info(service_name, 'relations').get(relation_name) |
4006 | + if relation is not None and relation['state'] == 'up': |
4007 | + break |
4008 | + if time.time() - start_time >= timeout: |
4009 | + raise RuntimeError('timeout waiting for relation to be up') |
4010 | + time.sleep(SLEEP_AMOUNT) |
4011 | + |
4012 | + |
4013 | +# DEPRECATED: client-side only |
4014 | +def wait_for_page_contents(url, contents, timeout=120, validate=None): |
4015 | + if validate is None: |
4016 | + validate = operator.contains |
4017 | + start_time = time.time() |
4018 | + while True: |
4019 | + try: |
4020 | + stream = urlopen(url) |
4021 | + except (HTTPError, URLError): |
4022 | + pass |
4023 | + else: |
4024 | + page = stream.read() |
4025 | + if validate(page, contents): |
4026 | + return page |
4027 | + if time.time() - start_time >= timeout: |
4028 | + raise RuntimeError('timeout waiting for contents of ' + url) |
4029 | + time.sleep(SLEEP_AMOUNT) |
4030 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/__pycache__/__init__.cpython-38.pyc |
4031 | new file mode 100644 |
4032 | index 0000000..797bc82 |
4033 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/charmhelpers/__pycache__/__init__.cpython-38.pyc differ |
4034 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/IMPORT b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/IMPORT |
4035 | new file mode 100644 |
4036 | index 0000000..554fddd |
4037 | --- /dev/null |
4038 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/IMPORT |
4039 | @@ -0,0 +1,14 @@ |
4040 | +Source: lp:charmsupport/trunk |
4041 | + |
4042 | +charmsupport/charmsupport/execd.py -> charm-helpers/charmhelpers/contrib/charmsupport/execd.py |
4043 | +charmsupport/charmsupport/hookenv.py -> charm-helpers/charmhelpers/contrib/charmsupport/hookenv.py |
4044 | +charmsupport/charmsupport/host.py -> charm-helpers/charmhelpers/contrib/charmsupport/host.py |
4045 | +charmsupport/charmsupport/nrpe.py -> charm-helpers/charmhelpers/contrib/charmsupport/nrpe.py |
4046 | +charmsupport/charmsupport/volumes.py -> charm-helpers/charmhelpers/contrib/charmsupport/volumes.py |
4047 | + |
4048 | +charmsupport/tests/test_execd.py -> charm-helpers/tests/contrib/charmsupport/test_execd.py |
4049 | +charmsupport/tests/test_hookenv.py -> charm-helpers/tests/contrib/charmsupport/test_hookenv.py |
4050 | +charmsupport/tests/test_host.py -> charm-helpers/tests/contrib/charmsupport/test_host.py |
4051 | +charmsupport/tests/test_nrpe.py -> charm-helpers/tests/contrib/charmsupport/test_nrpe.py |
4052 | + |
4053 | +charmsupport/bin/charmsupport -> charm-helpers/bin/contrib/charmsupport/charmsupport |
4054 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__init__.py b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__init__.py |
4055 | new file mode 100644 |
4056 | index 0000000..d7567b8 |
4057 | --- /dev/null |
4058 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__init__.py |
4059 | @@ -0,0 +1,13 @@ |
4060 | +# Copyright 2014-2015 Canonical Limited. |
4061 | +# |
4062 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
4063 | +# you may not use this file except in compliance with the License. |
4064 | +# You may obtain a copy of the License at |
4065 | +# |
4066 | +# http://www.apache.org/licenses/LICENSE-2.0 |
4067 | +# |
4068 | +# Unless required by applicable law or agreed to in writing, software |
4069 | +# distributed under the License is distributed on an "AS IS" BASIS, |
4070 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4071 | +# See the License for the specific language governing permissions and |
4072 | +# limitations under the License. |
4073 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/__init__.cpython-38.pyc |
4074 | new file mode 100644 |
4075 | index 0000000..e15454c |
4076 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/__init__.cpython-38.pyc differ |
4077 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/nrpe.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/nrpe.cpython-38.pyc |
4078 | new file mode 100644 |
4079 | index 0000000..2a370de |
4080 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/nrpe.cpython-38.pyc differ |
4081 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/volumes.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/volumes.cpython-38.pyc |
4082 | new file mode 100644 |
4083 | index 0000000..e1e32f3 |
4084 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/__pycache__/volumes.cpython-38.pyc differ |
4085 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/nrpe.py b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/nrpe.py |
4086 | new file mode 100644 |
4087 | index 0000000..8d1753c |
4088 | --- /dev/null |
4089 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/nrpe.py |
4090 | @@ -0,0 +1,522 @@ |
4091 | +# Copyright 2012-2021 Canonical Limited. |
4092 | +# |
4093 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
4094 | +# you may not use this file except in compliance with the License. |
4095 | +# You may obtain a copy of the License at |
4096 | +# |
4097 | +# http://www.apache.org/licenses/LICENSE-2.0 |
4098 | +# |
4099 | +# Unless required by applicable law or agreed to in writing, software |
4100 | +# distributed under the License is distributed on an "AS IS" BASIS, |
4101 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4102 | +# See the License for the specific language governing permissions and |
4103 | +# limitations under the License. |
4104 | + |
4105 | +"""Compatibility with the nrpe-external-master charm""" |
4106 | +# |
4107 | +# Authors: |
4108 | +# Matthew Wedgwood <matthew.wedgwood@canonical.com> |
4109 | + |
4110 | +import glob |
4111 | +import grp |
4112 | +import os |
4113 | +import pwd |
4114 | +import re |
4115 | +import shlex |
4116 | +import shutil |
4117 | +import subprocess |
4118 | +import yaml |
4119 | + |
4120 | +from charmhelpers.core.hookenv import ( |
4121 | + config, |
4122 | + hook_name, |
4123 | + local_unit, |
4124 | + log, |
4125 | + relation_get, |
4126 | + relation_ids, |
4127 | + relation_set, |
4128 | + relations_of_type, |
4129 | +) |
4130 | + |
4131 | +from charmhelpers.core.host import service |
4132 | +from charmhelpers.core import host |
4133 | + |
4134 | +# This module adds compatibility with the nrpe-external-master and plain nrpe |
4135 | +# subordinate charms. To use it in your charm: |
4136 | +# |
4137 | +# 1. Update metadata.yaml |
4138 | +# |
4139 | +# provides: |
4140 | +# (...) |
4141 | +# nrpe-external-master: |
4142 | +# interface: nrpe-external-master |
4143 | +# scope: container |
4144 | +# |
4145 | +# and/or |
4146 | +# |
4147 | +# provides: |
4148 | +# (...) |
4149 | +# local-monitors: |
4150 | +# interface: local-monitors |
4151 | +# scope: container |
4152 | + |
4153 | +# |
4154 | +# 2. Add the following to config.yaml |
4155 | +# |
4156 | +# nagios_context: |
4157 | +# default: "juju" |
4158 | +# type: string |
4159 | +# description: | |
4160 | +# Used by the nrpe subordinate charms. |
4161 | +# A string that will be prepended to instance name to set the host name |
4162 | +# in nagios. So for instance the hostname would be something like: |
4163 | +# juju-myservice-0 |
4164 | +# If you're running multiple environments with the same services in them |
4165 | +# this allows you to differentiate between them. |
4166 | +# nagios_servicegroups: |
4167 | +# default: "" |
4168 | +# type: string |
4169 | +# description: | |
4170 | +# A comma-separated list of nagios servicegroups. |
4171 | +# If left empty, the nagios_context will be used as the servicegroup |
4172 | +# |
4173 | +# 3. Add custom checks (Nagios plugins) to files/nrpe-external-master |
4174 | +# |
4175 | +# 4. Update your hooks.py with something like this: |
4176 | +# |
4177 | +# from charmsupport.nrpe import NRPE |
4178 | +# (...) |
4179 | +# def update_nrpe_config(): |
4180 | +# nrpe_compat = NRPE() |
4181 | +# nrpe_compat.add_check( |
4182 | +# shortname = "myservice", |
4183 | +# description = "Check MyService", |
4184 | +# check_cmd = "check_http -w 2 -c 10 http://localhost" |
4185 | +# ) |
4186 | +# nrpe_compat.add_check( |
4187 | +# "myservice_other", |
4188 | +# "Check for widget failures", |
4189 | +# check_cmd = "/srv/myapp/scripts/widget_check" |
4190 | +# ) |
4191 | +# nrpe_compat.write() |
4192 | +# |
4193 | +# def config_changed(): |
4194 | +# (...) |
4195 | +# update_nrpe_config() |
4196 | +# |
4197 | +# def nrpe_external_master_relation_changed(): |
4198 | +# update_nrpe_config() |
4199 | +# |
4200 | +# def local_monitors_relation_changed(): |
4201 | +# update_nrpe_config() |
4202 | +# |
4203 | +# 4.a If your charm is a subordinate charm set primary=False |
4204 | +# |
4205 | +# from charmsupport.nrpe import NRPE |
4206 | +# (...) |
4207 | +# def update_nrpe_config(): |
4208 | +# nrpe_compat = NRPE(primary=False) |
4209 | +# |
4210 | +# 5. ln -s hooks.py nrpe-external-master-relation-changed |
4211 | +# ln -s hooks.py local-monitors-relation-changed |
4212 | + |
4213 | + |
4214 | +class CheckException(Exception): |
4215 | + pass |
4216 | + |
4217 | + |
4218 | +class Check(object): |
4219 | + shortname_re = '[A-Za-z0-9-_.@]+$' |
4220 | + service_template = (""" |
4221 | +#--------------------------------------------------- |
4222 | +# This file is Juju managed |
4223 | +#--------------------------------------------------- |
4224 | +define service {{ |
4225 | + use active-service |
4226 | + host_name {nagios_hostname} |
4227 | + service_description {nagios_hostname}[{shortname}] """ |
4228 | + """{description} |
4229 | + check_command check_nrpe!{command} |
4230 | + servicegroups {nagios_servicegroup} |
4231 | +{service_config_overrides} |
4232 | +}} |
4233 | +""") |
4234 | + |
4235 | + def __init__(self, shortname, description, check_cmd, max_check_attempts=None): |
4236 | + super(Check, self).__init__() |
4237 | + # XXX: could be better to calculate this from the service name |
4238 | + if not re.match(self.shortname_re, shortname): |
4239 | + raise CheckException("shortname must match {}".format( |
4240 | + Check.shortname_re)) |
4241 | + self.shortname = shortname |
4242 | + self.command = "check_{}".format(shortname) |
4243 | + # Note: a set of invalid characters is defined by the |
4244 | + # Nagios server config |
4245 | + # The default is: illegal_object_name_chars=`~!$%^&*"|'<>?,()= |
4246 | + self.description = description |
4247 | + self.check_cmd = self._locate_cmd(check_cmd) |
4248 | + self.max_check_attempts = max_check_attempts |
4249 | + |
4250 | + def _get_check_filename(self): |
4251 | + return os.path.join(NRPE.nrpe_confdir, '{}.cfg'.format(self.command)) |
4252 | + |
4253 | + def _get_service_filename(self, hostname): |
4254 | + return os.path.join(NRPE.nagios_exportdir, |
4255 | + 'service__{}_{}.cfg'.format(hostname, self.command)) |
4256 | + |
4257 | + def _locate_cmd(self, check_cmd): |
4258 | + search_path = ( |
4259 | + '/usr/lib/nagios/plugins', |
4260 | + '/usr/local/lib/nagios/plugins', |
4261 | + ) |
4262 | + parts = shlex.split(check_cmd) |
4263 | + for path in search_path: |
4264 | + if os.path.exists(os.path.join(path, parts[0])): |
4265 | + command = os.path.join(path, parts[0]) |
4266 | + if len(parts) > 1: |
4267 | + command += " " + " ".join(parts[1:]) |
4268 | + return command |
4269 | + log('Check command not found: {}'.format(parts[0])) |
4270 | + return '' |
4271 | + |
4272 | + def _remove_service_files(self): |
4273 | + if not os.path.exists(NRPE.nagios_exportdir): |
4274 | + return |
4275 | + for f in os.listdir(NRPE.nagios_exportdir): |
4276 | + if f.endswith('_{}.cfg'.format(self.command)): |
4277 | + os.remove(os.path.join(NRPE.nagios_exportdir, f)) |
4278 | + |
4279 | + def remove(self, hostname): |
4280 | + nrpe_check_file = self._get_check_filename() |
4281 | + if os.path.exists(nrpe_check_file): |
4282 | + os.remove(nrpe_check_file) |
4283 | + self._remove_service_files() |
4284 | + |
4285 | + def write(self, nagios_context, hostname, nagios_servicegroups): |
4286 | + nrpe_check_file = self._get_check_filename() |
4287 | + with open(nrpe_check_file, 'w') as nrpe_check_config: |
4288 | + nrpe_check_config.write("# check {}\n".format(self.shortname)) |
4289 | + if nagios_servicegroups: |
4290 | + nrpe_check_config.write( |
4291 | + "# The following header was added automatically by juju\n") |
4292 | + nrpe_check_config.write( |
4293 | + "# Modifying it will affect nagios monitoring and alerting\n") |
4294 | + nrpe_check_config.write( |
4295 | + "# servicegroups: {}\n".format(nagios_servicegroups)) |
4296 | + nrpe_check_config.write("command[{}]={}\n".format( |
4297 | + self.command, self.check_cmd)) |
4298 | + |
4299 | + if not os.path.exists(NRPE.nagios_exportdir): |
4300 | + log('Not writing service config as {} is not accessible'.format( |
4301 | + NRPE.nagios_exportdir)) |
4302 | + else: |
4303 | + self.write_service_config(nagios_context, hostname, |
4304 | + nagios_servicegroups) |
4305 | + |
4306 | + def write_service_config(self, nagios_context, hostname, |
4307 | + nagios_servicegroups): |
4308 | + self._remove_service_files() |
4309 | + |
4310 | + if self.max_check_attempts: |
4311 | + service_config_overrides = ' max_check_attempts {}'.format( |
4312 | + self.max_check_attempts |
4313 | + ) # Note indentation is here rather than in the template to avoid trailing spaces |
4314 | + else: |
4315 | + service_config_overrides = '' # empty string to avoid printing 'None' |
4316 | + templ_vars = { |
4317 | + 'nagios_hostname': hostname, |
4318 | + 'nagios_servicegroup': nagios_servicegroups, |
4319 | + 'description': self.description, |
4320 | + 'shortname': self.shortname, |
4321 | + 'command': self.command, |
4322 | + 'service_config_overrides': service_config_overrides, |
4323 | + } |
4324 | + nrpe_service_text = Check.service_template.format(**templ_vars) |
4325 | + nrpe_service_file = self._get_service_filename(hostname) |
4326 | + with open(nrpe_service_file, 'w') as nrpe_service_config: |
4327 | + nrpe_service_config.write(str(nrpe_service_text)) |
4328 | + |
4329 | + def run(self): |
4330 | + subprocess.call(self.check_cmd) |
4331 | + |
4332 | + |
4333 | +class NRPE(object): |
4334 | + nagios_logdir = '/var/log/nagios' |
4335 | + nagios_exportdir = '/var/lib/nagios/export' |
4336 | + nrpe_confdir = '/etc/nagios/nrpe.d' |
4337 | + homedir = '/var/lib/nagios' # home dir provided by nagios-nrpe-server |
4338 | + |
4339 | + def __init__(self, hostname=None, primary=True): |
4340 | + super(NRPE, self).__init__() |
4341 | + self.config = config() |
4342 | + self.primary = primary |
4343 | + self.nagios_context = self.config['nagios_context'] |
4344 | + if 'nagios_servicegroups' in self.config and self.config['nagios_servicegroups']: |
4345 | + self.nagios_servicegroups = self.config['nagios_servicegroups'] |
4346 | + else: |
4347 | + self.nagios_servicegroups = self.nagios_context |
4348 | + self.unit_name = local_unit().replace('/', '-') |
4349 | + if hostname: |
4350 | + self.hostname = hostname |
4351 | + else: |
4352 | + nagios_hostname = get_nagios_hostname() |
4353 | + if nagios_hostname: |
4354 | + self.hostname = nagios_hostname |
4355 | + else: |
4356 | + self.hostname = "{}-{}".format(self.nagios_context, self.unit_name) |
4357 | + self.checks = [] |
4358 | + # Iff in an nrpe-external-master relation hook, set primary status |
4359 | + relation = relation_ids('nrpe-external-master') |
4360 | + if relation: |
4361 | + log("Setting charm primary status {}".format(primary)) |
4362 | + for rid in relation: |
4363 | + relation_set(relation_id=rid, relation_settings={'primary': self.primary}) |
4364 | + self.remove_check_queue = set() |
4365 | + |
4366 | + @classmethod |
4367 | + def does_nrpe_conf_dir_exist(cls): |
4368 | + """Return True if th nrpe_confdif directory exists.""" |
4369 | + return os.path.isdir(cls.nrpe_confdir) |
4370 | + |
4371 | + def add_check(self, *args, **kwargs): |
4372 | + shortname = None |
4373 | + if kwargs.get('shortname') is None: |
4374 | + if len(args) > 0: |
4375 | + shortname = args[0] |
4376 | + else: |
4377 | + shortname = kwargs['shortname'] |
4378 | + |
4379 | + self.checks.append(Check(*args, **kwargs)) |
4380 | + try: |
4381 | + self.remove_check_queue.remove(shortname) |
4382 | + except KeyError: |
4383 | + pass |
4384 | + |
4385 | + def remove_check(self, *args, **kwargs): |
4386 | + if kwargs.get('shortname') is None: |
4387 | + raise ValueError('shortname of check must be specified') |
4388 | + |
4389 | + # Use sensible defaults if they're not specified - these are not |
4390 | + # actually used during removal, but they're required for constructing |
4391 | + # the Check object; check_disk is chosen because it's part of the |
4392 | + # nagios-plugins-basic package. |
4393 | + if kwargs.get('check_cmd') is None: |
4394 | + kwargs['check_cmd'] = 'check_disk' |
4395 | + if kwargs.get('description') is None: |
4396 | + kwargs['description'] = '' |
4397 | + |
4398 | + check = Check(*args, **kwargs) |
4399 | + check.remove(self.hostname) |
4400 | + self.remove_check_queue.add(kwargs['shortname']) |
4401 | + |
4402 | + def write(self): |
4403 | + try: |
4404 | + nagios_uid = pwd.getpwnam('nagios').pw_uid |
4405 | + nagios_gid = grp.getgrnam('nagios').gr_gid |
4406 | + except Exception: |
4407 | + log("Nagios user not set up, nrpe checks not updated") |
4408 | + return |
4409 | + |
4410 | + if not os.path.exists(NRPE.nagios_logdir): |
4411 | + os.mkdir(NRPE.nagios_logdir) |
4412 | + os.chown(NRPE.nagios_logdir, nagios_uid, nagios_gid) |
4413 | + |
4414 | + nrpe_monitors = {} |
4415 | + monitors = {"monitors": {"remote": {"nrpe": nrpe_monitors}}} |
4416 | + |
4417 | + # check that the charm can write to the conf dir. If not, then nagios |
4418 | + # probably isn't installed, and we can defer. |
4419 | + if not self.does_nrpe_conf_dir_exist(): |
4420 | + return |
4421 | + |
4422 | + for nrpecheck in self.checks: |
4423 | + nrpecheck.write(self.nagios_context, self.hostname, |
4424 | + self.nagios_servicegroups) |
4425 | + nrpe_monitors[nrpecheck.shortname] = { |
4426 | + "command": nrpecheck.command, |
4427 | + } |
4428 | + # If we were passed max_check_attempts, add that to the relation data |
4429 | + if nrpecheck.max_check_attempts is not None: |
4430 | + nrpe_monitors[nrpecheck.shortname]['max_check_attempts'] = nrpecheck.max_check_attempts |
4431 | + |
4432 | + # update-status hooks are configured to firing every 5 minutes by |
4433 | + # default. When nagios-nrpe-server is restarted, the nagios server |
4434 | + # reports checks failing causing unnecessary alerts. Let's not restart |
4435 | + # on update-status hooks. |
4436 | + if not hook_name() == 'update-status': |
4437 | + service('restart', 'nagios-nrpe-server') |
4438 | + |
4439 | + monitor_ids = relation_ids("local-monitors") + \ |
4440 | + relation_ids("nrpe-external-master") |
4441 | + for rid in monitor_ids: |
4442 | + reldata = relation_get(unit=local_unit(), rid=rid) |
4443 | + if 'monitors' in reldata: |
4444 | + # update the existing set of monitors with the new data |
4445 | + old_monitors = yaml.safe_load(reldata['monitors']) |
4446 | + old_nrpe_monitors = old_monitors['monitors']['remote']['nrpe'] |
4447 | + # remove keys that are in the remove_check_queue |
4448 | + old_nrpe_monitors = {k: v for k, v in old_nrpe_monitors.items() |
4449 | + if k not in self.remove_check_queue} |
4450 | + # update/add nrpe_monitors |
4451 | + old_nrpe_monitors.update(nrpe_monitors) |
4452 | + old_monitors['monitors']['remote']['nrpe'] = old_nrpe_monitors |
4453 | + # write back to the relation |
4454 | + relation_set(relation_id=rid, monitors=yaml.dump(old_monitors)) |
4455 | + else: |
4456 | + # write a brand new set of monitors, as no existing ones. |
4457 | + relation_set(relation_id=rid, monitors=yaml.dump(monitors)) |
4458 | + |
4459 | + self.remove_check_queue.clear() |
4460 | + |
4461 | + |
4462 | +def get_nagios_hostcontext(relation_name='nrpe-external-master'): |
4463 | + """ |
4464 | + Query relation with nrpe subordinate, return the nagios_host_context |
4465 | + |
4466 | + :param str relation_name: Name of relation nrpe sub joined to |
4467 | + """ |
4468 | + for rel in relations_of_type(relation_name): |
4469 | + if 'nagios_host_context' in rel: |
4470 | + return rel['nagios_host_context'] |
4471 | + |
4472 | + |
4473 | +def get_nagios_hostname(relation_name='nrpe-external-master'): |
4474 | + """ |
4475 | + Query relation with nrpe subordinate, return the nagios_hostname |
4476 | + |
4477 | + :param str relation_name: Name of relation nrpe sub joined to |
4478 | + """ |
4479 | + for rel in relations_of_type(relation_name): |
4480 | + if 'nagios_hostname' in rel: |
4481 | + return rel['nagios_hostname'] |
4482 | + |
4483 | + |
4484 | +def get_nagios_unit_name(relation_name='nrpe-external-master'): |
4485 | + """ |
4486 | + Return the nagios unit name prepended with host_context if needed |
4487 | + |
4488 | + :param str relation_name: Name of relation nrpe sub joined to |
4489 | + """ |
4490 | + host_context = get_nagios_hostcontext(relation_name) |
4491 | + if host_context: |
4492 | + unit = "%s:%s" % (host_context, local_unit()) |
4493 | + else: |
4494 | + unit = local_unit() |
4495 | + return unit |
4496 | + |
4497 | + |
4498 | +def add_init_service_checks(nrpe, services, unit_name, immediate_check=True): |
4499 | + """ |
4500 | + Add checks for each service in list |
4501 | + |
4502 | + :param NRPE nrpe: NRPE object to add check to |
4503 | + :param list services: List of services to check |
4504 | + :param str unit_name: Unit name to use in check description |
4505 | + :param bool immediate_check: For sysv init, run the service check immediately |
4506 | + """ |
4507 | + for svc in services: |
4508 | + # Don't add a check for these services from neutron-gateway |
4509 | + if svc in ['ext-port', 'os-charm-phy-nic-mtu']: |
4510 | + next |
4511 | + |
4512 | + upstart_init = '/etc/init/%s.conf' % svc |
4513 | + sysv_init = '/etc/init.d/%s' % svc |
4514 | + |
4515 | + if host.init_is_systemd(service_name=svc): |
4516 | + nrpe.add_check( |
4517 | + shortname=svc, |
4518 | + description='process check {%s}' % unit_name, |
4519 | + check_cmd='check_systemd.py %s' % svc |
4520 | + ) |
4521 | + elif os.path.exists(upstart_init): |
4522 | + nrpe.add_check( |
4523 | + shortname=svc, |
4524 | + description='process check {%s}' % unit_name, |
4525 | + check_cmd='check_upstart_job %s' % svc |
4526 | + ) |
4527 | + elif os.path.exists(sysv_init): |
4528 | + cronpath = '/etc/cron.d/nagios-service-check-%s' % svc |
4529 | + checkpath = '%s/service-check-%s.txt' % (nrpe.homedir, svc) |
4530 | + croncmd = ( |
4531 | + '/usr/local/lib/nagios/plugins/check_exit_status.pl ' |
4532 | + '-e -s /etc/init.d/%s status' % svc |
4533 | + ) |
4534 | + cron_file = '*/5 * * * * root %s > %s\n' % (croncmd, checkpath) |
4535 | + f = open(cronpath, 'w') |
4536 | + f.write(cron_file) |
4537 | + f.close() |
4538 | + nrpe.add_check( |
4539 | + shortname=svc, |
4540 | + description='service check {%s}' % unit_name, |
4541 | + check_cmd='check_status_file.py -f %s' % checkpath, |
4542 | + ) |
4543 | + # if /var/lib/nagios doesn't exist open(checkpath, 'w') will fail |
4544 | + # (LP: #1670223). |
4545 | + if immediate_check and os.path.isdir(nrpe.homedir): |
4546 | + f = open(checkpath, 'w') |
4547 | + subprocess.call( |
4548 | + croncmd.split(), |
4549 | + stdout=f, |
4550 | + stderr=subprocess.STDOUT |
4551 | + ) |
4552 | + f.close() |
4553 | + os.chmod(checkpath, 0o644) |
4554 | + |
4555 | + |
4556 | +def copy_nrpe_checks(nrpe_files_dir=None): |
4557 | + """ |
4558 | + Copy the nrpe checks into place |
4559 | + |
4560 | + """ |
4561 | + NAGIOS_PLUGINS = '/usr/local/lib/nagios/plugins' |
4562 | + if nrpe_files_dir is None: |
4563 | + # determine if "charmhelpers" is in CHARMDIR or CHARMDIR/hooks |
4564 | + for segment in ['.', 'hooks']: |
4565 | + nrpe_files_dir = os.path.abspath(os.path.join( |
4566 | + os.getenv('CHARM_DIR'), |
4567 | + segment, |
4568 | + 'charmhelpers', |
4569 | + 'contrib', |
4570 | + 'openstack', |
4571 | + 'files')) |
4572 | + if os.path.isdir(nrpe_files_dir): |
4573 | + break |
4574 | + else: |
4575 | + raise RuntimeError("Couldn't find charmhelpers directory") |
4576 | + if not os.path.exists(NAGIOS_PLUGINS): |
4577 | + os.makedirs(NAGIOS_PLUGINS) |
4578 | + for fname in glob.glob(os.path.join(nrpe_files_dir, "check_*")): |
4579 | + if os.path.isfile(fname): |
4580 | + shutil.copy2(fname, |
4581 | + os.path.join(NAGIOS_PLUGINS, os.path.basename(fname))) |
4582 | + |
4583 | + |
4584 | +def add_haproxy_checks(nrpe, unit_name): |
4585 | + """ |
4586 | + Add checks for each service in list |
4587 | + |
4588 | + :param NRPE nrpe: NRPE object to add check to |
4589 | + :param str unit_name: Unit name to use in check description |
4590 | + """ |
4591 | + nrpe.add_check( |
4592 | + shortname='haproxy_servers', |
4593 | + description='Check HAProxy {%s}' % unit_name, |
4594 | + check_cmd='check_haproxy.sh') |
4595 | + nrpe.add_check( |
4596 | + shortname='haproxy_queue', |
4597 | + description='Check HAProxy queue depth {%s}' % unit_name, |
4598 | + check_cmd='check_haproxy_queue_depth.sh') |
4599 | + |
4600 | + |
4601 | +def remove_deprecated_check(nrpe, deprecated_services): |
4602 | + """ |
4603 | + Remove checks for deprecated services in list |
4604 | + |
4605 | + :param nrpe: NRPE object to remove check from |
4606 | + :type nrpe: NRPE |
4607 | + :param deprecated_services: List of deprecated services that are removed |
4608 | + :type deprecated_services: list |
4609 | + """ |
4610 | + for dep_svc in deprecated_services: |
4611 | + log('Deprecated service: {}'.format(dep_svc)) |
4612 | + nrpe.remove_check(shortname=dep_svc) |
4613 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/volumes.py b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/volumes.py |
4614 | new file mode 100644 |
4615 | index 0000000..f7c6fbd |
4616 | --- /dev/null |
4617 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/charmsupport/volumes.py |
4618 | @@ -0,0 +1,173 @@ |
4619 | +# Copyright 2014-2021 Canonical Limited. |
4620 | +# |
4621 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
4622 | +# you may not use this file except in compliance with the License. |
4623 | +# You may obtain a copy of the License at |
4624 | +# |
4625 | +# http://www.apache.org/licenses/LICENSE-2.0 |
4626 | +# |
4627 | +# Unless required by applicable law or agreed to in writing, software |
4628 | +# distributed under the License is distributed on an "AS IS" BASIS, |
4629 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4630 | +# See the License for the specific language governing permissions and |
4631 | +# limitations under the License. |
4632 | + |
4633 | +''' |
4634 | +Functions for managing volumes in juju units. One volume is supported per unit. |
4635 | +Subordinates may have their own storage, provided it is on its own partition. |
4636 | + |
4637 | +Configuration stanzas:: |
4638 | + |
4639 | + volume-ephemeral: |
4640 | + type: boolean |
4641 | + default: true |
4642 | + description: > |
4643 | + If false, a volume is mounted as specified in "volume-map" |
4644 | + If true, ephemeral storage will be used, meaning that log data |
4645 | + will only exist as long as the machine. YOU HAVE BEEN WARNED. |
4646 | + volume-map: |
4647 | + type: string |
4648 | + default: {} |
4649 | + description: > |
4650 | + YAML map of units to device names, e.g: |
4651 | + "{ rsyslog/0: /dev/vdb, rsyslog/1: /dev/vdb }" |
4652 | + Service units will raise a configure-error if volume-ephemeral |
4653 | + is 'true' and no volume-map value is set. Use 'juju set' to set a |
4654 | + value and 'juju resolved' to complete configuration. |
4655 | + |
4656 | +Usage:: |
4657 | + |
4658 | + from charmsupport.volumes import configure_volume, VolumeConfigurationError |
4659 | + from charmsupport.hookenv import log, ERROR |
4660 | + def post_mount_hook(): |
4661 | + stop_service('myservice') |
4662 | + def post_mount_hook(): |
4663 | + start_service('myservice') |
4664 | + |
4665 | + if __name__ == '__main__': |
4666 | + try: |
4667 | + configure_volume(before_change=pre_mount_hook, |
4668 | + after_change=post_mount_hook) |
4669 | + except VolumeConfigurationError: |
4670 | + log('Storage could not be configured', ERROR) |
4671 | + |
4672 | +''' |
4673 | + |
4674 | +# XXX: Known limitations |
4675 | +# - fstab is neither consulted nor updated |
4676 | + |
4677 | +import os |
4678 | +from charmhelpers.core import hookenv |
4679 | +from charmhelpers.core import host |
4680 | +import yaml |
4681 | + |
4682 | + |
4683 | +MOUNT_BASE = '/srv/juju/volumes' |
4684 | + |
4685 | + |
4686 | +class VolumeConfigurationError(Exception): |
4687 | + '''Volume configuration data is missing or invalid''' |
4688 | + pass |
4689 | + |
4690 | + |
4691 | +def get_config(): |
4692 | + '''Gather and sanity-check volume configuration data''' |
4693 | + volume_config = {} |
4694 | + config = hookenv.config() |
4695 | + |
4696 | + errors = False |
4697 | + |
4698 | + if config.get('volume-ephemeral') in (True, 'True', 'true', 'Yes', 'yes'): |
4699 | + volume_config['ephemeral'] = True |
4700 | + else: |
4701 | + volume_config['ephemeral'] = False |
4702 | + |
4703 | + try: |
4704 | + volume_map = yaml.safe_load(config.get('volume-map', '{}')) |
4705 | + except yaml.YAMLError as e: |
4706 | + hookenv.log("Error parsing YAML volume-map: {}".format(e), |
4707 | + hookenv.ERROR) |
4708 | + errors = True |
4709 | + if volume_map is None: |
4710 | + # probably an empty string |
4711 | + volume_map = {} |
4712 | + elif not isinstance(volume_map, dict): |
4713 | + hookenv.log("Volume-map should be a dictionary, not {}".format( |
4714 | + type(volume_map))) |
4715 | + errors = True |
4716 | + |
4717 | + volume_config['device'] = volume_map.get(os.environ['JUJU_UNIT_NAME']) |
4718 | + if volume_config['device'] and volume_config['ephemeral']: |
4719 | + # asked for ephemeral storage but also defined a volume ID |
4720 | + hookenv.log('A volume is defined for this unit, but ephemeral ' |
4721 | + 'storage was requested', hookenv.ERROR) |
4722 | + errors = True |
4723 | + elif not volume_config['device'] and not volume_config['ephemeral']: |
4724 | + # asked for permanent storage but did not define volume ID |
4725 | + hookenv.log('Ephemeral storage was requested, but there is no volume ' |
4726 | + 'defined for this unit.', hookenv.ERROR) |
4727 | + errors = True |
4728 | + |
4729 | + unit_mount_name = hookenv.local_unit().replace('/', '-') |
4730 | + volume_config['mountpoint'] = os.path.join(MOUNT_BASE, unit_mount_name) |
4731 | + |
4732 | + if errors: |
4733 | + return None |
4734 | + return volume_config |
4735 | + |
4736 | + |
4737 | +def mount_volume(config): |
4738 | + if os.path.exists(config['mountpoint']): |
4739 | + if not os.path.isdir(config['mountpoint']): |
4740 | + hookenv.log('Not a directory: {}'.format(config['mountpoint'])) |
4741 | + raise VolumeConfigurationError() |
4742 | + else: |
4743 | + host.mkdir(config['mountpoint']) |
4744 | + if os.path.ismount(config['mountpoint']): |
4745 | + unmount_volume(config) |
4746 | + if not host.mount(config['device'], config['mountpoint'], persist=True): |
4747 | + raise VolumeConfigurationError() |
4748 | + |
4749 | + |
4750 | +def unmount_volume(config): |
4751 | + if os.path.ismount(config['mountpoint']): |
4752 | + if not host.umount(config['mountpoint'], persist=True): |
4753 | + raise VolumeConfigurationError() |
4754 | + |
4755 | + |
4756 | +def managed_mounts(): |
4757 | + '''List of all mounted managed volumes''' |
4758 | + return filter(lambda mount: mount[0].startswith(MOUNT_BASE), host.mounts()) |
4759 | + |
4760 | + |
4761 | +def configure_volume(before_change=lambda: None, after_change=lambda: None): |
4762 | + '''Set up storage (or don't) according to the charm's volume configuration. |
4763 | + Returns the mount point or "ephemeral". before_change and after_change |
4764 | + are optional functions to be called if the volume configuration changes. |
4765 | + ''' |
4766 | + |
4767 | + config = get_config() |
4768 | + if not config: |
4769 | + hookenv.log('Failed to read volume configuration', hookenv.CRITICAL) |
4770 | + raise VolumeConfigurationError() |
4771 | + |
4772 | + if config['ephemeral']: |
4773 | + if os.path.ismount(config['mountpoint']): |
4774 | + before_change() |
4775 | + unmount_volume(config) |
4776 | + after_change() |
4777 | + return 'ephemeral' |
4778 | + else: |
4779 | + # persistent storage |
4780 | + if os.path.ismount(config['mountpoint']): |
4781 | + mounts = dict(managed_mounts()) |
4782 | + if mounts.get(config['mountpoint']) != config['device']: |
4783 | + before_change() |
4784 | + unmount_volume(config) |
4785 | + mount_volume(config) |
4786 | + after_change() |
4787 | + else: |
4788 | + before_change() |
4789 | + mount_volume(config) |
4790 | + after_change() |
4791 | + return config['mountpoint'] |
4792 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/database/__init__.py b/charms/appstream-generator/venv/charmhelpers/contrib/database/__init__.py |
4793 | new file mode 100644 |
4794 | index 0000000..64fac9d |
4795 | --- /dev/null |
4796 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/database/__init__.py |
4797 | @@ -0,0 +1,11 @@ |
4798 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
4799 | +# you may not use this file except in compliance with the License. |
4800 | +# You may obtain a copy of the License at |
4801 | +# |
4802 | +# http://www.apache.org/licenses/LICENSE-2.0 |
4803 | +# |
4804 | +# Unless required by applicable law or agreed to in writing, software |
4805 | +# distributed under the License is distributed on an "AS IS" BASIS, |
4806 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4807 | +# See the License for the specific language governing permissions and |
4808 | +# limitations under the License. |
4809 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/database/__pycache__/__init__.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/database/__pycache__/__init__.cpython-38.pyc |
4810 | new file mode 100644 |
4811 | index 0000000..5611c92 |
4812 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/database/__pycache__/__init__.cpython-38.pyc differ |
4813 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/database/__pycache__/mysql.cpython-38.pyc b/charms/appstream-generator/venv/charmhelpers/contrib/database/__pycache__/mysql.cpython-38.pyc |
4814 | new file mode 100644 |
4815 | index 0000000..a59ead9 |
4816 | Binary files /dev/null and b/charms/appstream-generator/venv/charmhelpers/contrib/database/__pycache__/mysql.cpython-38.pyc differ |
4817 | diff --git a/charms/appstream-generator/venv/charmhelpers/contrib/database/mysql.py b/charms/appstream-generator/venv/charmhelpers/contrib/database/mysql.py |
4818 | new file mode 100644 |
4819 | index 0000000..ca79924 |
4820 | --- /dev/null |
4821 | +++ b/charms/appstream-generator/venv/charmhelpers/contrib/database/mysql.py |
4822 | @@ -0,0 +1,840 @@ |
4823 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
4824 | +# you may not use this file except in compliance with the License. |
4825 | +# You may obtain a copy of the License at |
4826 | +# |
4827 | +# http://www.apache.org/licenses/LICENSE-2.0 |
4828 | +# |
4829 | +# Unless required by applicable law or agreed to in writing, software |
4830 | +# distributed under the License is distributed on an "AS IS" BASIS, |
4831 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
4832 | +# See the License for the specific language governing permissions and |
4833 | +# limitations under the License. |
4834 | + |
4835 | +"""Helper for working with a MySQL database""" |
4836 | +import collections |
4837 | +import copy |
4838 | +import json |
4839 | +import re |
4840 | +import sys |
4841 | +import platform |
4842 | +import os |
4843 | +import glob |
4844 | +import six |
4845 | + |
4846 | +# from string import upper |
4847 | + |
4848 | +from charmhelpers.core.host import ( |
4849 | + CompareHostReleases, |
4850 | + lsb_release, |
4851 | + mkdir, |
4852 | + pwgen, |
4853 | + write_file |
4854 | +) |
4855 | +from charmhelpers.core.hookenv import ( |
4856 | + config as config_get, |
4857 | + relation_get, |
4858 | + related_units, |
4859 | + unit_get, |
4860 | + log, |
4861 | + DEBUG, |
4862 | + ERROR, |
4863 | + INFO, |
4864 | + WARNING, |
4865 | + leader_get, |
4866 | + leader_set, |
4867 | + is_leader, |
4868 | +) |
4869 | +from charmhelpers.fetch import ( |
4870 | + apt_install, |
4871 | + apt_update, |
4872 | + filter_installed_packages, |
4873 | +) |
4874 | +from charmhelpers.contrib.network.ip import get_host_ip |
4875 | + |
4876 | +try: |
4877 | + import MySQLdb |
4878 | +except ImportError: |
4879 | + apt_update(fatal=True) |
4880 | + if six.PY2: |
4881 | + apt_install(filter_installed_packages(['python-mysqldb']), fatal=True) |
4882 | + else: |
4883 | + apt_install(filter_installed_packages(['python3-mysqldb']), fatal=True) |
4884 | + import MySQLdb |
4885 | + |
4886 | + |
4887 | +class MySQLSetPasswordError(Exception): |
4888 | + pass |
4889 | + |
4890 | + |
4891 | +class MySQLHelper(object): |
4892 | + |
4893 | + def __init__(self, rpasswdf_template, upasswdf_template, host='localhost', |
4894 | + migrate_passwd_to_leader_storage=True, |
4895 | + delete_ondisk_passwd_file=True, user="root", password=None, |
4896 | + port=None, connect_timeout=None): |
4897 | + self.user = user |
4898 | + self.host = host |
4899 | + self.password = password |
4900 | + self.port = port |
4901 | + # default timeout of 30 seconds. |
4902 | + self.connect_timeout = connect_timeout or 30 |
4903 | + |
4904 | + # Password file path templates |
4905 | + self.root_passwd_file_template = rpasswdf_template |
4906 | + self.user_passwd_file_template = upasswdf_template |
4907 | + |
4908 | + self.migrate_passwd_to_leader_storage = migrate_passwd_to_leader_storage |
4909 | + # If we migrate we have the option to delete local copy of root passwd |
4910 | + self.delete_ondisk_passwd_file = delete_ondisk_passwd_file |
4911 | + self.connection = None |
4912 | + |
4913 | + def connect(self, user='root', password=None, host=None, port=None, |
4914 | + connect_timeout=None): |
4915 | + _connection_info = { |
4916 | + "user": user or self.user, |
4917 | + "passwd": password or self.password, |
4918 | + "host": host or self.host |
4919 | + } |
4920 | + # set the connection timeout; for mysql8 it can hang forever, so some |
4921 | + # timeout is required. |
4922 | + timeout = connect_timeout or self.connect_timeout |
4923 | + if timeout: |
4924 | + _connection_info["connect_timeout"] = timeout |
4925 | + # port cannot be None but we also do not want to specify it unless it |
4926 | + # has been explicit set. |
4927 | + port = port or self.port |
4928 | + if port is not None: |
4929 | + _connection_info["port"] = port |
4930 | + |
4931 | + log("Opening db connection for %s@%s" % (user, host), level=DEBUG) |
4932 | + try: |
4933 | + self.connection = MySQLdb.connect(**_connection_info) |
4934 | + except Exception as e: |
4935 | + log("Failed to connect to database due to '{}'".format(str(e)), |
4936 | + level=ERROR) |
4937 | + raise |
4938 | + |
4939 | + def database_exists(self, db_name): |
4940 | + cursor = self.connection.cursor() |
4941 | + try: |
4942 | + cursor.execute("SHOW DATABASES") |
4943 | + databases = [i[0] for i in cursor.fetchall()] |
4944 | + finally: |
4945 | + cursor.close() |
4946 | + |
4947 | + return db_name in databases |
4948 | + |
4949 | + def create_database(self, db_name): |
4950 | + cursor = self.connection.cursor() |
4951 | + try: |
4952 | + cursor.execute("CREATE DATABASE `{}` CHARACTER SET UTF8" |
4953 | + .format(db_name)) |
4954 | + finally: |
4955 | + cursor.close() |
4956 | + |
4957 | + def grant_exists(self, db_name, db_user, remote_ip): |
4958 | + cursor = self.connection.cursor() |
4959 | + priv_string = "GRANT ALL PRIVILEGES ON `{}`.* " \ |
4960 | + "TO '{}'@'{}'".format(db_name, db_user, remote_ip) |
4961 | + try: |
4962 | + cursor.execute("SHOW GRANTS for '{}'@'{}'".format(db_user, |
4963 | + remote_ip)) |
4964 | + grants = [i[0] for i in cursor.fetchall()] |
4965 | + except MySQLdb.OperationalError: |
4966 | + return False |
4967 | + finally: |
4968 | + cursor.close() |
4969 | + |
4970 | + # TODO: review for different grants |
4971 | + return priv_string in grants |
4972 | + |
4973 | + def create_grant(self, db_name, db_user, remote_ip, password): |
4974 | + cursor = self.connection.cursor() |
4975 | + try: |
4976 | + # TODO: review for different grants |
4977 | + cursor.execute("GRANT ALL PRIVILEGES ON `{}`.* TO '{}'@'{}' " |
4978 | + "IDENTIFIED BY '{}'".format(db_name, |
4979 | + db_user, |
4980 | + remote_ip, |
4981 | + password)) |
4982 | + finally: |
4983 | + cursor.close() |
4984 | + |
4985 | + def create_admin_grant(self, db_user, remote_ip, password): |
4986 | + cursor = self.connection.cursor() |
4987 | + try: |
4988 | + cursor.execute("GRANT ALL PRIVILEGES ON *.* TO '{}'@'{}' " |
4989 | + "IDENTIFIED BY '{}'".format(db_user, |
4990 | + remote_ip, |
4991 | + password)) |
4992 | + finally: |
4993 | + cursor.close() |
4994 | + |
4995 | + def cleanup_grant(self, db_user, remote_ip): |
4996 | + cursor = self.connection.cursor() |
4997 | + try: |
4998 | + cursor.execute("DROP FROM mysql.user WHERE user='{}' " |
4999 | + "AND HOST='{}'".format(db_user, |
5000 | + remote_ip)) |
The diff has been truncated for viewing.