Build separately for each supported series and use binary builds

Charms for OpenStack Yoga supports both Ubuntu Focal and Jammy
which means Python 3.8 and Python 3.10.  Managing dependencies
across those two versions is non-trivial and we need to build
the charm on the series the charm is supposed to support.

Switch to using a binary build which allows pip's dependency
resolution to work.

This patch also drops the impish bundle and fixes channels
for auxiliary charms.

Update metadata with jammy support.

Replace `octavia.setup.ensure_lts_images` with the default glance
lts image configure job.

Drop python build dependencies in wheelhouse and let the binary
build figure those out automatically.

Closes-Bug: #1915171
Change-Id: I744a8903be7450b5d9b2af3f96c6f61d206f9271
This commit is contained in:
Corey Bryant 2022-09-22 13:00:06 +00:00 committed by Frode Nordahl
parent 975502813f
commit 7cb77afe26
No known key found for this signature in database
GPG Key ID: 6A5D59A3BA48373F
12 changed files with 133 additions and 118 deletions

View File

@ -8,28 +8,49 @@ parts:
- python3-dev - python3-dev
- libffi-dev - libffi-dev
- libssl-dev - libssl-dev
- libxml2-dev
- libxslt1-dev
- rustc
- cargo
build-environment:
- MAKEFLAGS: -j$(nproc)
override-build: | override-build: |
apt-get install ca-certificates -y apt-get install ca-certificates -y
tox -e build-reactive tox -e build-reactive
override-stage: | override-stage: |
echo "Copying charm to staging area: $CHARMCRAFT_STAGE" echo "Copying charm to staging area: $CRAFT_STAGE"
NAME=$(ls $CHARMCRAFT_PART_BUILD/build/builds) NAME=$(ls $CRAFT_PART_BUILD/build/builds)
cp -r $CHARMCRAFT_PART_BUILD/build/builds/$NAME/* $CHARMCRAFT_STAGE/ cp -r $CRAFT_PART_BUILD/build/builds/$NAME/* $CRAFT_STAGE/
override-prime: | override-prime: |
# For some reason, the normal priming chokes on the fact that there's a # For some reason, the normal priming chokes on the fact that there's a
# hooks directory. # hooks directory.
cp -r $CHARMCRAFT_STAGE/* . cp -r $CRAFT_STAGE/* .
# Charmcraft looks for this specific entry point.
mkdir src
ln -sf ../hooks/start src/charm.py
bases: bases:
- build-on: - name: ubuntu
- name: ubuntu channel: "20.04"
channel: "20.04" architectures: [amd64]
architectures: - name: ubuntu
- amd64 channel: "20.04"
run-on: architectures: [arm64]
- name: ubuntu - name: ubuntu
channel: "20.04" channel: "20.04"
architectures: [amd64, s390x, ppc64el, arm64] architectures: [ppc64el]
- name: ubuntu - name: ubuntu
channel: "22.04" channel: "20.04"
architectures: [amd64, s390x, ppc64el, arm64] architectures: [s390x]
- name: ubuntu
channel: "22.04"
architectures: [amd64]
- name: ubuntu
channel: "22.04"
architectures: [arm64]
- name: ubuntu
channel: "22.04"
architectures: [ppc64el]
- name: ubuntu
channel: "22.04"
architectures: [s390x]

View File

@ -18,6 +18,7 @@
needs_charm_build: true needs_charm_build: true
charm_build_name: octavia charm_build_name: octavia
build_type: charmcraft build_type: charmcraft
charmcraft_channel: 2.0/stable
- job: - job:
name: focal-xena-ha name: focal-xena-ha

View File

@ -19,7 +19,7 @@ tags:
- openstack - openstack
series: series:
- focal - focal
- impish - jammy
subordinate: false subordinate: false
provides: provides:
nrpe-external-master: nrpe-external-master:

View File

@ -114,30 +114,30 @@ applications:
channel: yoga/edge channel: yoga/edge
octavia-mysql-router: octavia-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
keystone-mysql-router: keystone-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
nova-mysql-router: nova-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
glance-mysql-router: glance-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
neutron-mysql-router: neutron-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
placement-mysql-router: placement-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
mysql-innodb-cluster: mysql-innodb-cluster:
constraints: mem=3072M constraints: mem=3072M
charm: ch:mysql-innodb-cluster charm: ch:mysql-innodb-cluster
num_units: 3 num_units: 3
channel: 8.0.19/edge channel: 8.0/edge
neutron-api: neutron-api:
constraints: cores=4 constraints: cores=4
charm: ch:neutron-api charm: ch:neutron-api
@ -171,12 +171,15 @@ applications:
charm: ch:hacluster charm: ch:hacluster
channel: 2.0.3/edge channel: 2.0.3/edge
ovn-chassis-octavia: ovn-chassis-octavia:
series: *series
charm: ch:ovn-chassis charm: ch:ovn-chassis
channel: latest/edge channel: 22.03/edge
options:
ovn-source: distro
octavia: octavia:
constraints: cores=8 constraints: cores=8
series: *series series: *series
charm: ../../../octavia.charm charm: ../../../octavia_ubuntu-20.04-amd64.charm
num_units: 3 num_units: 3
options: options:
openstack-origin: *openstack-origin openstack-origin: *openstack-origin
@ -191,13 +194,20 @@ applications:
num_units: 1 num_units: 1
options: options:
use_swift: False use_swift: False
mirror_list: "[{url: 'http://cloud-images.ubuntu.com/releases/',
name_prefix: 'ubuntu:released',
path: 'streams/v1/index.sjson', max: 1,
item_filters: [
'release~(focal)',
'arch~(x86_64|amd64)',
'ftype~(disk1.img|disk.img)']}]"
channel: yoga/edge channel: yoga/edge
octavia-diskimage-retrofit: octavia-diskimage-retrofit:
charm: ch:octavia-diskimage-retrofit charm: ch:octavia-diskimage-retrofit
options: options:
amp-image-tag: 'octavia-amphora' amp-image-tag: 'octavia-amphora'
retrofit-series: *series retrofit-series: *series
retrofit-uca-pocket: wallaby retrofit-uca-pocket: xena
channel: yoga/edge channel: yoga/edge
placement: placement:
charm: ch:placement charm: ch:placement
@ -216,10 +226,12 @@ applications:
num_units: 3 num_units: 3
options: options:
source: *openstack-origin source: *openstack-origin
channel: latest/edge channel: 22.03/edge
ovn-chassis: ovn-chassis:
charm: ch:ovn-chassis charm: ch:ovn-chassis
channel: latest/edge channel: 22.03/edge
options:
ovn-source: distro
vault: vault:
charm: ch:vault charm: ch:vault
num_units: 1 num_units: 1

View File

@ -201,7 +201,7 @@ applications:
octavia: octavia:
constraints: cores=8 constraints: cores=8
series: *series series: *series
charm: ../../../octavia.charm charm: ../../../octavia_ubuntu-20.04-amd64.charm
num_units: 3 num_units: 3
options: options:
openstack-origin: *openstack-origin openstack-origin: *openstack-origin
@ -219,6 +219,13 @@ applications:
num_units: 1 num_units: 1
options: options:
use_swift: False use_swift: False
mirror_list: "[{url: 'http://cloud-images.ubuntu.com/releases/',
name_prefix: 'ubuntu:released',
path: 'streams/v1/index.sjson', max: 1,
item_filters: [
'release~(focal)',
'arch~(x86_64|amd64)',
'ftype~(disk1.img|disk.img)']}]"
channel: yoga/edge channel: yoga/edge
octavia-diskimage-retrofit: octavia-diskimage-retrofit:
series: *series series: *series
@ -226,7 +233,7 @@ applications:
options: options:
amp-image-tag: 'octavia-amphora' amp-image-tag: 'octavia-amphora'
retrofit-series: *series retrofit-series: *series
retrofit-uca-pocket: wallaby retrofit-uca-pocket: xena
channel: yoga/edge channel: yoga/edge
placement: placement:
series: *series series: *series

View File

@ -171,12 +171,13 @@ applications:
charm: ch:hacluster charm: ch:hacluster
channel: 2.0.3/edge channel: 2.0.3/edge
ovn-chassis-octavia: ovn-chassis-octavia:
series: *series
charm: ch:ovn-chassis charm: ch:ovn-chassis
channel: latest/edge channel: 22.03/edge
octavia: octavia:
constraints: cores=8 constraints: cores=8
series: *series series: *series
charm: ../../../octavia.charm charm: ../../../octavia_ubuntu-20.04-amd64.charm
num_units: 3 num_units: 3
options: options:
openstack-origin: *openstack-origin openstack-origin: *openstack-origin
@ -191,13 +192,20 @@ applications:
num_units: 1 num_units: 1
options: options:
use_swift: False use_swift: False
mirror_list: "[{url: 'http://cloud-images.ubuntu.com/releases/',
name_prefix: 'ubuntu:released',
path: 'streams/v1/index.sjson', max: 1,
item_filters: [
'release~(focal)',
'arch~(x86_64|amd64)',
'ftype~(disk1.img|disk.img)']}]"
channel: yoga/edge channel: yoga/edge
octavia-diskimage-retrofit: octavia-diskimage-retrofit:
charm: ch:octavia-diskimage-retrofit charm: ch:octavia-diskimage-retrofit
options: options:
amp-image-tag: 'octavia-amphora' amp-image-tag: 'octavia-amphora'
retrofit-series: *series retrofit-series: *series
retrofit-uca-pocket: wallaby retrofit-uca-pocket: yoga
channel: yoga/edge channel: yoga/edge
placement: placement:
charm: ch:placement charm: ch:placement
@ -216,10 +224,10 @@ applications:
num_units: 3 num_units: 3
options: options:
source: *openstack-origin source: *openstack-origin
channel: latest/edge channel: 22.03/edge
ovn-chassis: ovn-chassis:
charm: ch:ovn-chassis charm: ch:ovn-chassis
channel: latest/edge channel: 22.03/edge
vault: vault:
charm: ch:vault charm: ch:vault
num_units: 1 num_units: 1

View File

@ -187,7 +187,7 @@ applications:
octavia: octavia:
constraints: cores=8 constraints: cores=8
series: *series series: *series
charm: ../../../octavia.charm charm: ../../../octavia_ubuntu-20.04-amd64.charm
num_units: 3 num_units: 3
options: options:
openstack-origin: *openstack-origin openstack-origin: *openstack-origin
@ -203,13 +203,20 @@ applications:
num_units: 1 num_units: 1
options: options:
use_swift: False use_swift: False
mirror_list: "[{url: 'http://cloud-images.ubuntu.com/releases/',
name_prefix: 'ubuntu:released',
path: 'streams/v1/index.sjson', max: 1,
item_filters: [
'release~(focal)',
'arch~(x86_64|amd64)',
'ftype~(disk1.img|disk.img)']}]"
channel: yoga/edge channel: yoga/edge
octavia-diskimage-retrofit: octavia-diskimage-retrofit:
charm: ch:octavia-diskimage-retrofit charm: ch:octavia-diskimage-retrofit
options: options:
amp-image-tag: 'octavia-amphora' amp-image-tag: 'octavia-amphora'
retrofit-series: *series retrofit-series: *series
retrofit-uca-pocket: wallaby retrofit-uca-pocket: yoga
channel: yoga/edge channel: yoga/edge
placement: placement:
charm: ch:placement charm: ch:placement

View File

@ -114,30 +114,30 @@ applications:
channel: yoga/edge channel: yoga/edge
octavia-mysql-router: octavia-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
keystone-mysql-router: keystone-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
nova-mysql-router: nova-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
glance-mysql-router: glance-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
neutron-mysql-router: neutron-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
placement-mysql-router: placement-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
mysql-innodb-cluster: mysql-innodb-cluster:
constraints: mem=3072M constraints: mem=3072M
charm: ch:mysql-innodb-cluster charm: ch:mysql-innodb-cluster
num_units: 3 num_units: 3
channel: 8.0.19/edge channel: 8.0/edge
neutron-api: neutron-api:
constraints: cores=4 constraints: cores=4
charm: ch:neutron-api charm: ch:neutron-api
@ -169,14 +169,15 @@ applications:
hacluster-octavia: hacluster-octavia:
series: *series series: *series
charm: ch:hacluster charm: ch:hacluster
channel: 2.0.3/edge channel: 2.4/edge
ovn-chassis-octavia: ovn-chassis-octavia:
series: *series
charm: ch:ovn-chassis charm: ch:ovn-chassis
channel: latest/edge channel: latest/edge
octavia: octavia:
constraints: cores=8 constraints: cores=8
series: *series series: *series
charm: ../../../octavia.charm charm: ../../../octavia_ubuntu-22.04-amd64.charm
num_units: 3 num_units: 3
options: options:
openstack-origin: *openstack-origin openstack-origin: *openstack-origin
@ -185,7 +186,7 @@ applications:
rabbitmq-server: rabbitmq-server:
charm: ch:rabbitmq-server charm: ch:rabbitmq-server
num_units: 1 num_units: 1
channel: 3.8/edge channel: 3.9/edge
glance-simplestreams-sync: glance-simplestreams-sync:
charm: ch:glance-simplestreams-sync charm: ch:glance-simplestreams-sync
num_units: 1 num_units: 1
@ -195,16 +196,16 @@ applications:
name_prefix: 'ubuntu:released', name_prefix: 'ubuntu:released',
path: 'streams/v1/index.sjson', max: 1, path: 'streams/v1/index.sjson', max: 1,
item_filters: [ item_filters: [
'release~(bionic|focal|hirsute)', 'release~(jammy)',
'arch~(x86_64|amd64)', 'arch~(x86_64|amd64)',
'ftype~(disk1.img|disk.img)']}]" 'ftype~(disk1.img|disk.img)']}]"
channel: yoga/edge channel: latest/edge
octavia-diskimage-retrofit: octavia-diskimage-retrofit:
charm: ch:octavia-diskimage-retrofit charm: ch:octavia-diskimage-retrofit
options: options:
amp-image-tag: 'octavia-amphora' amp-image-tag: 'octavia-amphora'
retrofit-series: *series retrofit-series: *series
channel: yoga/edge channel: latest/edge
placement: placement:
charm: ch:placement charm: ch:placement
num_units: 1 num_units: 1

View File

@ -106,30 +106,30 @@ applications:
channel: yoga/edge channel: yoga/edge
octavia-mysql-router: octavia-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
keystone-mysql-router: keystone-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
nova-mysql-router: nova-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
glance-mysql-router: glance-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
neutron-mysql-router: neutron-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
placement-mysql-router: placement-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
vault-mysql-router: vault-mysql-router:
charm: ch:mysql-router charm: ch:mysql-router
channel: 8.0.19/edge channel: 8.0/edge
mysql-innodb-cluster: mysql-innodb-cluster:
constraints: mem=3072M constraints: mem=3072M
charm: ch:mysql-innodb-cluster charm: ch:mysql-innodb-cluster
num_units: 3 num_units: 3
channel: 8.0.19/edge channel: 8.0/edge
neutron-api: neutron-api:
charm: ch:neutron-api charm: ch:neutron-api
num_units: 1 num_units: 1
@ -181,13 +181,14 @@ applications:
debug: True debug: True
channel: yoga/edge channel: yoga/edge
hacluster-octavia: hacluster-octavia:
series: *series
charm: ch:hacluster charm: ch:hacluster
num_units: 0 num_units: 0
channel: 2.0.3/edge channel: 2.4/edge
octavia: octavia:
constraints: cores=8 constraints: cores=8
series: *series series: *series
charm: ../../../octavia.charm charm: ../../../octavia_ubuntu-22.04-amd64.charm
num_units: 3 num_units: 3
options: options:
openstack-origin: *openstack-origin openstack-origin: *openstack-origin
@ -197,7 +198,7 @@ applications:
rabbitmq-server: rabbitmq-server:
charm: ch:rabbitmq-server charm: ch:rabbitmq-server
num_units: 1 num_units: 1
channel: 3.8/edge channel: 3.9/edge
glance-simplestreams-sync: glance-simplestreams-sync:
charm: ch:glance-simplestreams-sync charm: ch:glance-simplestreams-sync
num_units: 1 num_units: 1
@ -207,16 +208,16 @@ applications:
name_prefix: 'ubuntu:released', name_prefix: 'ubuntu:released',
path: 'streams/v1/index.sjson', max: 1, path: 'streams/v1/index.sjson', max: 1,
item_filters: [ item_filters: [
'release~(bionic|focal|hirsute)', 'release~(jammy)',
'arch~(x86_64|amd64)', 'arch~(x86_64|amd64)',
'ftype~(disk1.img|disk.img)']}]" 'ftype~(disk1.img|disk.img)']}]"
channel: yoga/edge channel: latest/edge
octavia-diskimage-retrofit: octavia-diskimage-retrofit:
charm: ch:octavia-diskimage-retrofit charm: ch:octavia-diskimage-retrofit
options: options:
amp-image-tag: 'octavia-amphora' amp-image-tag: 'octavia-amphora'
retrofit-series: *series retrofit-series: *series
channel: yoga/edge channel: latest/edge
placement: placement:
charm: ch:placement charm: ch:placement
num_units: 1 num_units: 1

View File

@ -44,7 +44,7 @@ target_deploy_status:
configure: configure:
- zaza.openstack.charm_tests.vault.setup.auto_initialize - zaza.openstack.charm_tests.vault.setup.auto_initialize
- zaza.openstack.charm_tests.glance_simplestreams_sync.setup.sync_images - zaza.openstack.charm_tests.glance_simplestreams_sync.setup.sync_images
- zaza.openstack.charm_tests.octavia.setup.ensure_lts_images - zaza.openstack.charm_tests.glance.setup.add_lts_image
- zaza.openstack.charm_tests.octavia.diskimage_retrofit.setup.retrofit_amphora_image - zaza.openstack.charm_tests.octavia.diskimage_retrofit.setup.retrofit_amphora_image
- zaza.openstack.charm_tests.octavia.setup.configure_octavia - zaza.openstack.charm_tests.octavia.setup.configure_octavia
- zaza.openstack.charm_tests.nova.setup.create_flavors - zaza.openstack.charm_tests.nova.setup.create_flavors

View File

@ -1,41 +1,12 @@
# cachetools > 4.2.1 requires setuptools >= 46.4 which breaks most install targets
cachetools<4.2.2
# Several dependencies now require setuptools-scm>=3.0,<=3.4.1 which requires toml
setuptools-scm>=3.0,<=3.4.1
toml
keystoneauth1
pbr
python-novaclient
python-neutronclient
# REMOVEME -- fix for https://github.com/pyparsing/pyparsing/issues/164
pyparsing==2.4.2
poetry-core
neutron_lib
# neutron-lib indirectly requires Tempits (neutron-lib -> oslo.db -> sqlalchemy-migrate -> Tempita) # neutron-lib indirectly requires Tempits (neutron-lib -> oslo.db -> sqlalchemy-migrate -> Tempita)
# and Tempita is incompatible with setuptools 58+ # and Tempita is incompatible with setuptools 58+
Tempita<0.5 Tempita<0.5
pytest-runner
# python-zipp 2.x introduces a requirement for setuptools 42.x which is not available.
# resolve conflict:
# layer-basic requires setuptools<42, zipp>=2.0.0 requires setuptools>42
# LP: #1862186
zipp<2.0.0
# Mako, importlib_metadata, importlib_resources, cmd2, pytest-runner, soupsieve, cliff all pinned
# for compat with setuptools<42
importlib_metadata<3.1.0
importlib_resources<4.1.0
cmd2<1.5.0
pytest-runner<5.3.0
soupsieve<2.2
Mako<1.2.0
cliff<3.9.0 # cliff 3.9 includes dep on autopage which is dep on setuptools>42
keystoneauth1
python-novaclient
python-neutronclient
neutron_lib
tenacity tenacity
# cryptography 3.4 introduces a requirement for rust code in the module. As it has to be compiled
# on the machine during install, this breaks installs. Instead pin to <3.4 until a solution can be
# found that doesn't require compiling on the target machine.
# LP: #1915171
cryptography<3.4
git+https://github.com/openstack/charms.openstack.git#egg=charms.openstack git+https://github.com/openstack/charms.openstack.git#egg=charms.openstack

20
tox.ini
View File

@ -11,18 +11,6 @@ envlist = pep8,py3
sitepackages = False sitepackages = False
# NOTE: Avoid false positives by not skipping missing interpreters. # NOTE: Avoid false positives by not skipping missing interpreters.
skip_missing_interpreters = False skip_missing_interpreters = False
# NOTES:
# * We avoid the new dependency resolver by pinning pip < 20.3, see
# https://github.com/pypa/pip/issues/9187
# * Pinning dependencies requires tox >= 3.2.0, see
# https://tox.readthedocs.io/en/latest/config.html#conf-requires
# * It is also necessary to pin virtualenv as a newer virtualenv would still
# lead to fetching the latest pip in the func* tox targets, see
# https://stackoverflow.com/a/38133283
requires =
pip < 20.3
virtualenv < 20.0
setuptools<50.0.0
# NOTE: https://wiki.canonical.com/engineering/OpenStack/InstallLatestToxOnOsci # NOTE: https://wiki.canonical.com/engineering/OpenStack/InstallLatestToxOnOsci
minversion = 3.18.0 minversion = 3.18.0
@ -41,7 +29,6 @@ allowlist_externals =
charmcraft charmcraft
bash bash
tox tox
rename.sh
deps = deps =
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
@ -50,13 +37,12 @@ basepython = python3
deps = -r{toxinidir}/build-requirements.txt deps = -r{toxinidir}/build-requirements.txt
commands = commands =
charmcraft clean charmcraft clean
charmcraft -v build charmcraft -v pack
{toxinidir}/rename.sh
[testenv:build-reactive] [testenv:build-reactive]
basepython = python3 basepython = python3
commands = commands =
charm-build --log-level DEBUG --use-lock-file-branches -o {toxinidir}/build/builds src {posargs} charm-build --log-level DEBUG --use-lock-file-branches --binary-wheels-from-source -o {toxinidir}/build/builds src {posargs}
[testenv:add-build-lock-file] [testenv:add-build-lock-file]
basepython = python3 basepython = python3
@ -96,7 +82,7 @@ commands = stestr run --slowest {posargs}
[testenv:pep8] [testenv:pep8]
basepython = python3 basepython = python3
deps = flake8==3.9.2 deps = flake8==3.9.2
charm-tools==2.8.3 git+https://github.com/juju/charm-tools.git
commands = flake8 {posargs} src unit_tests commands = flake8 {posargs} src unit_tests
[testenv:func-target] [testenv:func-target]