diff --git a/.gitreview b/.gitreview index 659ee49..0e80cea 100644 --- a/.gitreview +++ b/.gitreview @@ -2,3 +2,5 @@ host=review.opendev.org port=29418 project=openstack/charm-glance.git + +defaultbranch=stable/2023.2 diff --git a/build-requirements.txt b/build-requirements.txt deleted file mode 100644 index b6d2452..0000000 --- a/build-requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# NOTES(lourot): -# * We don't install charmcraft via pip anymore because it anyway spins up a -# container and scp the system's charmcraft snap inside it. So the charmcraft -# snap is necessary on the system anyway. -# * `tox -e build` successfully validated with charmcraft 1.2.1 - -cffi==1.14.6; python_version < '3.6' # cffi 1.15.0 drops support for py35. diff --git a/charm-helpers-hooks.yaml b/charm-helpers-hooks.yaml index 5d56aae..763046c 100644 --- a/charm-helpers-hooks.yaml +++ b/charm-helpers-hooks.yaml @@ -1,4 +1,4 @@ -repo: https://github.com/juju/charm-helpers +repo: https://github.com/juju/charm-helpers@stable/bobcat destination: charmhelpers include: - core diff --git a/charmcraft.yaml b/charmcraft.yaml index 62a8f5b..d02699c 100644 --- a/charmcraft.yaml +++ b/charmcraft.yaml @@ -21,19 +21,8 @@ parts: - metadata.yaml - README.md -bases: - - build-on: - - name: ubuntu - channel: "22.04" - architectures: - - amd64 - run-on: - - name: ubuntu - channel: "22.04" - architectures: [amd64, s390x, ppc64el, arm64] - - name: ubuntu - channel: "23.04" - architectures: [amd64, s390x, ppc64el, arm64] - - name: ubuntu - channel: "23.10" - architectures: [amd64, s390x, ppc64el, arm64] +platforms: + ubuntu@22.04:amd64: + ubuntu@22.04:arm64: + ubuntu@22.04:ppc64el: + ubuntu@22.04:s390x: diff --git a/charmhelpers/contrib/network/ip.py b/charmhelpers/contrib/network/ip.py index cf9926b..f3b4864 100644 --- a/charmhelpers/contrib/network/ip.py +++ b/charmhelpers/contrib/network/ip.py @@ -16,6 +16,7 @@ import re import subprocess import socket +import ssl from functools import partial @@ -527,19 +528,56 @@ def get_hostname(address, fqdn=True): return result.split('.')[0] -def port_has_listener(address, port): +class SSLPortCheckInfo(object): + + def __init__(self, key, cert, ca_cert, check_hostname=False): + self.key = key + self.cert = cert + self.ca_cert = ca_cert + # NOTE: by default we do not check hostname since the port check is + # typically performed using 0.0.0.0 which will not match the + # certificate. Hence the default for this is False. + self.check_hostname = check_hostname + + @property + def ssl_context(self): + context = ssl.create_default_context() + context.check_hostname = self.check_hostname + context.load_cert_chain(self.cert, self.key) + context.load_verify_locations(self.ca_cert) + return context + + +def port_has_listener(address, port, sslinfo=None): """ Returns True if the address:port is open and being listened to, - else False. + else False. By default uses netcat to check ports but if sslinfo is + provided will use an SSL connection instead. @param address: an IP address or hostname @param port: integer port + @param sslinfo: optional SSLPortCheckInfo object. + If provided, the check is performed using an ssl + connection. Note calls 'zc' via a subprocess shell """ - cmd = ['nc', '-z', address, str(port)] - result = subprocess.call(cmd) - return not (bool(result)) + if not sslinfo: + cmd = ['nc', '-z', address, str(port)] + result = subprocess.call(cmd) + return not (bool(result)) + + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + ssock = sslinfo.ssl_context.wrap_socket(sock, + server_hostname=address) + ssock.connect((address, port)) + # this bit is crucial to ensure tls close_notify is sent + ssock.unwrap() + + return True + except ConnectionRefusedError: + return False def assert_charm_supports_ipv6(): diff --git a/charmhelpers/contrib/openstack/context.py b/charmhelpers/contrib/openstack/context.py index 42f1503..cd70b55 100644 --- a/charmhelpers/contrib/openstack/context.py +++ b/charmhelpers/contrib/openstack/context.py @@ -202,6 +202,21 @@ def get_related(self): return self.related +class KeystoneAuditMiddleware(OSContextGenerator): + def __init__(self, service: str) -> None: + self.service_name = service + + def __call__(self): + """Return context dictionary containing configuration status of + audit-middleware and the charm service name. + """ + ctxt = { + 'audit_middleware': config('audit-middleware') or False, + 'service_name': self.service_name + } + return ctxt + + class SharedDBContext(OSContextGenerator): interfaces = ['shared-db'] @@ -545,7 +560,7 @@ def _resolve(key): 'internal_auth_url': internal_auth_url, }) - # we keep all veriables in ctxt for compatibility and + # we keep all variables in ctxt for compatibility and # add nested dictionary for keystone_authtoken generic # templating if keystonemiddleware_os_release: @@ -557,6 +572,7 @@ def _resolve(key): # NOTE(jamespage) this is required for >= icehouse # so a missing value just indicates keystone needs # upgrading + ctxt['admin_user_id'] = _resolve('service_user_id') ctxt['admin_tenant_id'] = _resolve('service_tenant_id') ctxt['admin_domain_id'] = _resolve('service_domain_id') return ctxt diff --git a/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications b/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications new file mode 100644 index 0000000..1f88014 --- /dev/null +++ b/charmhelpers/contrib/openstack/templates/section-audit-middleware-notifications @@ -0,0 +1,4 @@ +{% if audit_middleware -%} +[audit_middleware_notifications] +driver = log +{% endif -%} \ No newline at end of file diff --git a/charmhelpers/contrib/openstack/templates/section-filter-audit b/charmhelpers/contrib/openstack/templates/section-filter-audit new file mode 100644 index 0000000..11512ae --- /dev/null +++ b/charmhelpers/contrib/openstack/templates/section-filter-audit @@ -0,0 +1,6 @@ +{% if audit_middleware and service_name -%} +[filter:audit] +paste.filter_factory = keystonemiddleware.audit:filter_factory +audit_map_file = /etc/{{ service_name }}/api_audit_map.conf +service_name = {{ service_name }} +{% endif -%} \ No newline at end of file diff --git a/charmhelpers/contrib/openstack/utils.py b/charmhelpers/contrib/openstack/utils.py index e98be2c..eefe34d 100644 --- a/charmhelpers/contrib/openstack/utils.py +++ b/charmhelpers/contrib/openstack/utils.py @@ -416,17 +416,6 @@ def get_os_version_codename(codename, version_map=OPENSTACK_CODENAMES, error_out(e) -def get_os_version_codename_swift(codename): - '''Determine OpenStack version number of swift from codename.''' - # for k, v in six.iteritems(SWIFT_CODENAMES): - for k, v in SWIFT_CODENAMES.items(): - if k == codename: - return v[-1] - e = 'Could not derive swift version for '\ - 'codename: %s' % codename - error_out(e) - - def get_swift_codename(version): '''Determine OpenStack codename that corresponds to swift version.''' codenames = [k for k, v in SWIFT_CODENAMES.items() if version in v] @@ -585,7 +574,6 @@ def _do_install(): return openstack_release().get('OPENSTACK_CODENAME') -@cached def openstack_release(): """Return /etc/os-release in a dict.""" d = {} @@ -847,14 +835,10 @@ def openstack_upgrade_available(package): if not cur_vers: # The package has not been installed yet do not attempt upgrade return False - if "swift" in package: - codename = get_os_codename_install_source(src) - avail_vers = get_os_version_codename_swift(codename) - else: - try: - avail_vers = get_os_version_install_source(src) - except Exception: - avail_vers = cur_vers + try: + avail_vers = get_os_version_install_source(src) + except Exception: + avail_vers = cur_vers apt.init() return apt.version_compare(avail_vers, cur_vers) >= 1 @@ -1222,12 +1206,14 @@ def _ows_check_services_running(services, ports): return ows_check_services_running(services, ports) -def ows_check_services_running(services, ports): +def ows_check_services_running(services, ports, ssl_check_info=None): """Check that the services that should be running are actually running and that any ports specified are being listened to. @param services: list of strings OR dictionary specifying services/ports @param ports: list of ports + @param ssl_check_info: SSLPortCheckInfo object. If provided, port checks + will be done using an SSL connection. @returns state, message: strings or None, None """ messages = [] @@ -1243,7 +1229,7 @@ def ows_check_services_running(services, ports): # also verify that the ports that should be open are open # NB, that ServiceManager objects only OPTIONALLY have ports map_not_open, ports_open = ( - _check_listening_on_services_ports(services)) + _check_listening_on_services_ports(services, ssl_check_info)) if not all(ports_open): # find which service has missing ports. They are in service # order which makes it a bit easier. @@ -1258,7 +1244,8 @@ def ows_check_services_running(services, ports): if ports is not None: # and we can also check ports which we don't know the service for - ports_open, ports_open_bools = _check_listening_on_ports_list(ports) + ports_open, ports_open_bools = \ + _check_listening_on_ports_list(ports, ssl_check_info) if not all(ports_open_bools): messages.append( "Ports which should be open, but are not: {}" @@ -1317,7 +1304,8 @@ def _check_running_services(services): return list(zip(services, services_running)), services_running -def _check_listening_on_services_ports(services, test=False): +def _check_listening_on_services_ports(services, test=False, + ssl_check_info=None): """Check that the unit is actually listening (has the port open) on the ports that the service specifies are open. If test is True then the function returns the services with ports that are open rather than @@ -1327,11 +1315,14 @@ def _check_listening_on_services_ports(services, test=False): @param services: OrderedDict(service: [port, ...], ...) @param test: default=False, if False, test for closed, otherwise open. + @param ssl_check_info: SSLPortCheckInfo object. If provided, port checks + will be done using an SSL connection. @returns OrderedDict(service: [port-not-open, ...]...), [boolean] """ test = not (not (test)) # ensure test is True or False all_ports = list(itertools.chain(*services.values())) - ports_states = [port_has_listener('0.0.0.0', p) for p in all_ports] + ports_states = [port_has_listener('0.0.0.0', p, ssl_check_info) + for p in all_ports] map_ports = OrderedDict() matched_ports = [p for p, opened in zip(all_ports, ports_states) if opened == test] # essentially opened xor test @@ -1342,16 +1333,19 @@ def _check_listening_on_services_ports(services, test=False): return map_ports, ports_states -def _check_listening_on_ports_list(ports): +def _check_listening_on_ports_list(ports, ssl_check_info=None): """Check that the ports list given are being listened to Returns a list of ports being listened to and a list of the booleans. + @param ssl_check_info: SSLPortCheckInfo object. If provided, port checks + will be done using an SSL connection. @param ports: LIST of port numbers. @returns [(port_num, boolean), ...], [boolean] """ - ports_open = [port_has_listener('0.0.0.0', p) for p in ports] + ports_open = [port_has_listener('0.0.0.0', p, ssl_check_info) + for p in ports] return zip(ports, ports_open), ports_open diff --git a/charmhelpers/core/host.py b/charmhelpers/core/host.py index 70dde6a..def403c 100644 --- a/charmhelpers/core/host.py +++ b/charmhelpers/core/host.py @@ -256,8 +256,11 @@ def service_resume(service_name, init_dir="/etc/init", upstart_file = os.path.join(init_dir, "{}.conf".format(service_name)) sysv_file = os.path.join(initd_dir, service_name) if init_is_systemd(service_name=service_name): - service('unmask', service_name) - service('enable', service_name) + if service('is-enabled', service_name): + log('service {} already enabled'.format(service_name), level=DEBUG) + else: + service('unmask', service_name) + service('enable', service_name) elif os.path.exists(upstart_file): override_path = os.path.join( init_dir, '{}.override'.format(service_name)) diff --git a/config.yaml b/config.yaml index ef79421..05d90d5 100644 --- a/config.yaml +++ b/config.yaml @@ -12,6 +12,11 @@ options: default: False description: | Setting this to True will allow supporting services to log to syslog. + audit-middleware: + type: boolean + default: False + description: | + Enable Keystone auditing middleware for logging API calls. openstack-origin: type: string default: bobcat diff --git a/hooks/glance_contexts.py b/hooks/glance_contexts.py index d91c168..65d3683 100644 --- a/hooks/glance_contexts.py +++ b/hooks/glance_contexts.py @@ -33,6 +33,7 @@ ApacheSSLContext as SSLContext, BindHostContext, VolumeAPIContext, + IdentityServiceContext, ) from charmhelpers.contrib.hahelpers.cluster import ( @@ -367,6 +368,7 @@ def __call__(self): # backend cinder_volume_type should be left blank so that glance # creates volume in cinder without specifying any volume type. if cinder_volume_types: + keystone_ctx = IdentityServiceContext()() for volume_type in volume_types: ctxt['enabled_backend_configs'][volume_type] = { 'cinder_volume_type': volume_type, @@ -374,6 +376,17 @@ def __call__(self): 'cinder_state_transition_timeout': config( 'cinder-state-transition-timeout'), } + if keystone_ctx: + ctxt['enabled_backend_configs'][volume_type].update({ + 'cinder_store_user_name': keystone_ctx.get( + 'admin_user'), + 'cinder_store_password': keystone_ctx.get( + 'admin_password'), + 'cinder_store_project_name': keystone_ctx.get( + 'admin_tenant_name'), + 'cinder_store_auth_address': keystone_ctx.get( + 'keystone_authtoken').get('auth_url'), + }) else: # default cinder volume type cinder ctxt['enabled_backend_configs']['cinder'] = { @@ -387,7 +400,7 @@ def __call__(self): vol_api_ctxt = VolumeAPIContext('glance-common')() volume_catalog_info = vol_api_ctxt['volume_catalog_info'] for volume_type in volume_types: - if 'volume_type' not in ctxt['enabled_backend_configs']: + if volume_type not in ctxt['enabled_backend_configs']: ctxt['enabled_backend_configs'][volume_type] = {} ctxt['enabled_backend_configs'][volume_type].update( {'cinder_catalog_info': volume_catalog_info}) diff --git a/hooks/glance_relations.py b/hooks/glance_relations.py index 97a71d0..5659b1c 100755 --- a/hooks/glance_relations.py +++ b/hooks/glance_relations.py @@ -487,6 +487,7 @@ def cluster_changed(): @harden() def upgrade_charm(): resolve_CONFIGS() + apt_update() apt_install(filter_installed_packages(determine_packages()), fatal=True) packages_removed = remove_old_packages() backup_deprecated_configurations() diff --git a/hooks/glance_utils.py b/hooks/glance_utils.py index d1f5a02..8053cb8 100644 --- a/hooks/glance_utils.py +++ b/hooks/glance_utils.py @@ -121,13 +121,13 @@ CHARM = "glance" GLANCE_CONF_DIR = "/etc/glance" +GLANCE_AUDIT_MAP = "%s/api_audit_map.conf" % GLANCE_CONF_DIR GLANCE_REGISTRY_CONF = "%s/glance-registry.conf" % GLANCE_CONF_DIR GLANCE_API_CONF = "%s/glance-api.conf" % GLANCE_CONF_DIR GLANCE_SWIFT_CONF = "%s/glance-swift.conf" % GLANCE_CONF_DIR GLANCE_REGISTRY_PASTE = os.path.join(GLANCE_CONF_DIR, 'glance-registry-paste.ini') -GLANCE_API_PASTE = os.path.join(GLANCE_CONF_DIR, - 'glance-api-paste.ini') +GLANCE_API_PASTE = os.path.join(GLANCE_CONF_DIR, 'api-paste.ini') GLANCE_POLICY_FILE = os.path.join(GLANCE_CONF_DIR, "policy.json") # NOTE(ajkavanagh): from Ussuri, glance switched to policy-in-code; this is the # policy.yaml file (as there is not packaged policy.json or .yaml) that is used @@ -204,6 +204,7 @@ def ceph_config_file(): config_file=GLANCE_API_CONF), context.MemcacheContext(), glance_contexts.GlanceImageImportContext(), + context.KeystoneAuditMiddleware(service=CHARM), glance_contexts.ExternalS3Context()], 'services': ['glance-api'] }), @@ -218,6 +219,14 @@ def ceph_config_file(): 'hook_contexts': [], 'services': ['glance-api', 'glance-registry'] }), + (GLANCE_AUDIT_MAP, { + 'hook_contexts': [context.KeystoneAuditMiddleware(service=CHARM)], + 'services': ['glance-api'] + }), + (GLANCE_API_PASTE, { + 'hook_contexts': [context.KeystoneAuditMiddleware(service=CHARM)], + 'services': ['glance-api'] + }), (ceph_config_file(), { 'hook_contexts': [context.CephContext()], 'services': ['glance-api', 'glance-registry'] @@ -257,7 +266,9 @@ def register_configs(): confs = [GLANCE_REGISTRY_CONF, GLANCE_API_CONF, - HAPROXY_CONF] + HAPROXY_CONF, + GLANCE_API_PASTE, + GLANCE_AUDIT_MAP] if relation_ids('ceph'): mkdir(os.path.dirname(ceph_config_file())) @@ -403,6 +414,8 @@ def restart_map(): cmp_release = CompareOpenStackReleases(os_release('glance-common')) for f, ctxt in CONFIG_FILES.items(): + if f == GLANCE_AUDIT_MAP and cmp_release < 'yoga': + continue svcs = [] for svc in ctxt['services']: if cmp_release >= 'stein' and svc == 'glance-registry': @@ -636,7 +649,7 @@ def reinstall_paste_ini(force_reinstall=False): for paste_file in [GLANCE_REGISTRY_PASTE, GLANCE_API_PASTE]: if os.path.exists(paste_file): - os.remove(paste_file) + os.replace(paste_file, f'{paste_file}.charm.upgrade') # glance-registry is deprecated at queens but still # installed. if cmp_release < 'rocky': @@ -647,6 +660,15 @@ def reinstall_paste_ini(force_reinstall=False): apt_install(packages=pkg_list, options=REINSTALL_OPTIONS, fatal=True) + # LP: #2042792 Restore original paste files + for paste_file in [GLANCE_REGISTRY_PASTE, + GLANCE_API_PASTE]: + if not os.path.exists(paste_file): + if os.path.exists(f'{paste_file}.charm.upgrade'): + os.replace(f'{paste_file}.charm.upgrade', paste_file) + else: + if os.path.exists(f'{paste_file}.charm.upgrade'): + os.remove(f'{paste_file}.charm.upgrade') db.set(PASTE_INI_MARKER, True) db.flush() diff --git a/merged-requirements-py310.txt b/merged-requirements-py310.txt new file mode 100644 index 0000000..c20d48e --- /dev/null +++ b/merged-requirements-py310.txt @@ -0,0 +1,762 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --output-file=merged-requirements-py310.txt --unsafe-package=juju --unsafe-package=kubernetes requirements.in test-requirements.in +# +aiohappyeyeballs==2.6.2 + # via aiohttp +aiohttp==3.14.0 + # via + # python-libmaas + # zaza +aiosignal==1.4.0 + # via aiohttp +aodhclient==3.11.0 + # via zaza-openstack +argcomplete==3.6.3 + # via python-libmaas +async-generator==1.10 + # via + # zaza + # zaza-openstack +async-timeout==5.0.1 + # via aiohttp +attrs==26.1.0 + # via + # aiohttp + # jsonschema +babel==2.18.0 + # via + # python-cinderclient + # python-heatclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient +backports-datetime-fromisoformat==2.0.3 + # via juju +backports-strenum==1.3.1 + # via juju +bcrypt==5.0.0 + # via paramiko +blessings==1.7 + # via charm-tools +boto3==1.43.22 + # via zaza-openstack +botocore==1.43.22 + # via + # boto3 + # s3transfer +certifi==2026.5.20 + # via + # kubernetes + # requests +cffi==2.0.0 + # via + # cryptography + # pynacl +charm-tools @ git+https://github.com/juju/charm-tools.git + # via -r test-requirements.in +charset-normalizer==3.4.7 + # via requests +cheetah3==3.2.6.post1 + # via charm-tools +cliff==2.18.0 + # via + # -r test-requirements.in + # aodhclient + # gnocchiclient + # osc-lib + # python-barbicanclient + # python-cloudkittyclient + # python-designateclient + # python-heatclient + # python-ironicclient + # python-neutronclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient + # stestr +cmd2==0.8.9 + # via cliff +colander==1.8.3 + # via charm-tools +colorclass==2.2.2 + # via python-libmaas +coverage==7.14.1 + # via -r test-requirements.in +croniter==6.2.2 + # via -r test-requirements.in +cryptography==3.3.2 + # via + # -r requirements.in + # openstacksdk + # paramiko + # pyopenssl + # python-magnumclient + # secretstorage + # trustme + # zaza + # zaza-openstack +debtcollector==3.1.0 + # via + # gnocchiclient + # oslo-concurrency + # oslo-config + # oslo-log + # oslo-utils + # python-designateclient + # python-keystoneclient + # python-manilaclient + # python-neutronclient +decorator==5.3.1 + # via + # dogpile-cache + # jsonpath-rw + # openstacksdk + # python-magnumclient +dict2colander==0.2 + # via charm-tools +distlib==0.4.1 + # via virtualenv +dnspython==2.8.0 + # via + # -r requirements.in + # pymongo + # zaza-openstack +dogpile-cache==1.5.0 + # via + # openstacksdk + # python-ironicclient +fasteners==0.20 + # via oslo-concurrency +filelock==3.29.1 + # via virtualenv +fixtures==4.3.2 + # via stestr +flake8==7.1.1 + # via -r test-requirements.in +frozenlist==1.8.0 + # via + # aiohttp + # aiosignal +futurist==1.10.0 + # via + # gnocchiclient + # zaza-openstack +gnocchiclient==7.2.0 + # via zaza-openstack +google-auth==2.47.0 + # via kubernetes +hvac==0.6.4 + # via + # juju + # zaza + # zaza-openstack +idna==3.18 + # via + # requests + # trustme + # yarl +importlib-metadata==9.0.0 + # via keyring +invoke==3.0.3 + # via paramiko +iso8601==2.1.0 + # via + # colander + # gnocchiclient + # keystoneauth1 + # openstacksdk + # oslo-utils + # python-ceilometerclient + # python-heatclient + # python-neutronclient + # python-novaclient + # python-subunit +jaraco-classes==3.4.0 + # via keyring +jeepney==0.9.0 + # via + # keyring + # secretstorage +jinja2==3.1.6 + # via + # -r requirements.in + # zaza + # zaza-openstack +jmespath==1.1.0 + # via + # boto3 + # botocore + # openstacksdk +jsonpatch==1.33 + # via + # openstacksdk + # warlock +jsonpath-rw==1.4.0 + # via jsonpath-rw-ext +jsonpath-rw-ext==1.2.2 + # via python-cloudkittyclient +jsonpointer==3.1.1 + # via jsonpatch +jsonschema==4.17.3 + # via + # charm-tools + # python-designateclient + # python-ironicclient + # warlock +juju-wait==2.8.4 + # via zaza +jujubundlelib==0.5.7 + # via charm-tools +keyring==23.13.1 + # via charm-tools +keystoneauth1==5.14.0 + # via + # aodhclient + # gnocchiclient + # openstacksdk + # osc-lib + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-cloudkittyclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient +lxml==6.1.1 + # via zaza-openstack +macaroonbakery==1.3.4 + # via + # juju + # python-libmaas + # zaza +markupsafe==3.0.3 + # via jinja2 +mccabe==0.7.0 + # via flake8 +more-itertools==11.1.0 + # via jaraco-classes +msgpack==1.1.2 + # via oslo-serialization +multidict==6.7.1 + # via + # aiohttp + # yarl +mypy-extensions==1.1.0 + # via typing-inspect +netaddr==0.7.20 + # via + # -r requirements.in + # oslo-config + # oslo-utils + # osprofiler + # python-neutronclient +netifaces==0.11.0 + # via + # -r requirements.in + # openstacksdk + # oslo-utils + # python-octaviaclient +oauthlib==3.3.1 + # via + # kubernetes + # python-libmaas + # requests-oauthlib +openstacksdk==4.1.0 + # via + # os-client-config + # osc-lib + # python-ironicclient + # python-magnumclient + # python-openstackclient +os-client-config==2.3.0 + # via + # python-cloudkittyclient + # python-neutronclient +os-service-types==1.8.2 + # via + # keystoneauth1 + # openstacksdk +osc-lib==2.1.0 + # via + # aodhclient + # python-cloudkittyclient + # python-designateclient + # python-heatclient + # python-ironicclient + # python-magnumclient + # python-neutronclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient + # zaza-openstack +oslo-concurrency==7.5.0 + # via osprofiler +oslo-config==6.11.3 + # via + # oslo-concurrency + # oslo-log + # osprofiler + # python-keystoneclient + # python-manilaclient + # zaza + # zaza-openstack +oslo-context==6.4.0 + # via oslo-log +oslo-i18n==6.8.0 + # via + # aodhclient + # osc-lib + # oslo-concurrency + # oslo-config + # oslo-log + # oslo-utils + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-glanceclient + # python-heatclient + # python-keystoneclient + # python-magnumclient + # python-neutronclient + # python-novaclient + # python-openstackclient + # python-watcherclient +oslo-log==8.2.0 + # via + # python-cloudkittyclient + # python-magnumclient + # python-manilaclient + # python-neutronclient +oslo-serialization==5.10.0 + # via + # aodhclient + # oslo-log + # osprofiler + # python-barbicanclient + # python-ceilometerclient + # python-designateclient + # python-heatclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-watcherclient +oslo-utils==7.1.0 + # via + # aodhclient + # osc-lib + # oslo-concurrency + # oslo-log + # oslo-serialization + # osprofiler + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-cloudkittyclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient +osprofiler==4.4.0 + # via aodhclient +otherstuf==1.1.0 + # via charm-tools +packaging==26.2 + # via + # juju + # oslo-utils +paramiko==5.0.0 + # via juju +parse==1.22.1 + # via stuf +path==16.16.0 + # via charm-tools +pathspec==0.10.3 + # via charm-tools +pbr==5.6.0 + # via + # -r requirements.in + # aodhclient + # cliff + # futurist + # jsonpath-rw-ext + # keystoneauth1 + # openstacksdk + # os-client-config + # os-service-types + # osc-lib + # oslo-concurrency + # oslo-context + # oslo-i18n + # oslo-log + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-cloudkittyclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient +pika==1.4.1 + # via zaza-openstack +pip==26.1.2 + # via charm-tools +platformdirs==4.10.0 + # via + # openstacksdk + # python-ironicclient + # virtualenv +ply==3.11 + # via jsonpath-rw +prettytable==0.7.2 + # via + # cliff + # futurist + # osprofiler + # python-ceilometerclient + # python-cinderclient + # python-glanceclient + # python-heatclient + # python-magnumclient + # python-manilaclient + # python-novaclient +propcache==0.5.2 + # via + # aiohttp + # yarl +protobuf==7.35.0 + # via macaroonbakery +psutil==1.2.1 + # via + # -r requirements.in + # -r test-requirements.in +pyasn1==0.6.3 + # via + # juju + # pyasn1-modules + # rsa +pyasn1-modules==0.4.2 + # via google-auth +pycodestyle==2.12.1 + # via flake8 +pycparser==3.0 + # via cffi +pyflakes==3.2.0 + # via flake8 +pymacaroons==0.13.0 + # via macaroonbakery +pymongo==4.17.0 + # via python-libmaas +pynacl==1.6.2 + # via + # macaroonbakery + # paramiko + # pymacaroons +pyopenssl==21.0.0 + # via + # python-glanceclient + # zaza-openstack +pyparsing==2.4.7 + # via + # -r test-requirements.in + # aodhclient + # cliff + # cmd2 + # oslo-utils +pyperclip==1.11.0 + # via cmd2 +pyrfc3339==1.1 + # via macaroonbakery +pyrsistent==0.20.0 + # via jsonschema +python-barbicanclient==4.10.0 + # via zaza-openstack +python-ceilometerclient==2.9.0 + # via zaza-openstack +python-cinderclient==5.0.2 + # via + # python-openstackclient + # zaza-openstack +python-cloudkittyclient==4.1.0 + # via zaza-openstack +python-dateutil==2.9.0.post0 + # via + # botocore + # croniter + # gnocchiclient + # kubernetes + # oslo-log +python-designateclient==2.12.0 + # via zaza-openstack +python-glanceclient==4.12.0 + # via + # python-openstackclient + # zaza-openstack +python-heatclient==1.18.1 + # via zaza-openstack +python-ironicclient==5.8.1 + # via zaza-openstack +python-keystoneclient==3.21.0 + # via + # python-manilaclient + # python-neutronclient + # python-openstackclient + # zaza-openstack +python-libmaas==0.6.8 + # via zaza +python-magnumclient==4.10.0 + # via zaza-openstack +python-manilaclient==1.29.0 + # via zaza-openstack +python-neutronclient==6.14.1 + # via + # python-octaviaclient + # zaza-openstack +python-novaclient==15.1.1 + # via + # python-openstackclient + # zaza-openstack +python-octaviaclient==1.10.1 + # via zaza-openstack +python-openstackclient==4.0.2 + # via python-octaviaclient +python-subunit==1.4.6 + # via stestr +python-swiftclient==3.8.1 + # via + # python-heatclient + # zaza-openstack +python-watcherclient==4.10.0 + # via zaza-openstack +pytz==2026.2 + # via + # pyrfc3339 + # python-libmaas +pyudev==0.24.4 + # via -r test-requirements.in +pyyaml==6.0.3 + # via + # charm-tools + # cliff + # juju + # juju-wait + # jujubundlelib + # kubernetes + # openstacksdk + # oslo-config + # oslo-utils + # python-cloudkittyclient + # python-heatclient + # python-ironicclient + # python-libmaas + # python-subunit + # python-watcherclient + # stestr + # zaza + # zaza-openstack +requests==2.34.2 + # via + # -r test-requirements.in + # charm-tools + # hvac + # keystoneauth1 + # kubernetes + # macaroonbakery + # oslo-config + # osprofiler + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-octaviaclient + # python-swiftclient + # requests-oauthlib +requests-oauthlib==2.0.0 + # via kubernetes +requestsexceptions==1.4.0 + # via openstacksdk +requirements-parser==0.5.0 + # via charm-tools +rfc3986==2.0.0 + # via oslo-config +rsa==4.9.1 + # via google-auth +ruamel-yaml==0.17.40 + # via charm-tools +ruamel-yaml-clib==0.2.15 + # via ruamel-yaml +s3transfer==0.18.0 + # via boto3 +secretstorage==3.3.3 + # via + # charm-tools + # keyring +setuptools==81.0.0 + # via + # -r test-requirements.in + # charm-tools + # colander +simplejson==4.1.1 + # via + # -r requirements.in + # osc-lib + # python-cinderclient + # python-manilaclient + # python-neutronclient + # python-novaclient +six==1.17.0 + # via + # -r requirements.in + # blessings + # cliff + # cmd2 + # cryptography + # futurist + # jsonpath-rw + # kubernetes + # macaroonbakery + # oslo-config + # pymacaroons + # pyopenssl + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-dateutil + # python-designateclient + # python-heatclient + # python-keystoneclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-swiftclient +stestr==4.2.1 + # via -r test-requirements.in +stevedore==5.8.0 + # via + # cliff + # dogpile-cache + # keystoneauth1 + # osc-lib + # oslo-config + # python-ceilometerclient + # python-designateclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient +stuf==0.9.16 + # via otherstuf +tenacity==9.1.4 + # via + # zaza + # zaza-openstack +terminaltables==3.1.10 + # via python-libmaas +testtools==2.9.1 + # via + # python-subunit + # stestr +tomlkit==0.15.0 + # via stestr +toposort==1.10 + # via juju +translationstring==1.4 + # via colander +trustme==1.2.1 + # via zaza-openstack +types-setuptools==82.0.0.20260518 + # via requirements-parser +typing-extensions==4.15.0 + # via + # aiohttp + # aiosignal + # dogpile-cache + # juju + # keystoneauth1 + # multidict + # os-service-types + # oslo-context + # typing-inspect + # virtualenv +typing-inspect==0.9.0 + # via juju +tzdata==2026.2 + # via oslo-utils +ujson==5.12.1 + # via gnocchiclient +urllib3==2.7.0 + # via + # botocore + # kubernetes + # requests +virtualenv==20.39.1 + # via charm-tools +voluptuous==0.16.0 + # via stestr +warlock==2.1.0 + # via python-glanceclient +wcwidth==0.7.0 + # via cmd2 +webob==1.8.10 + # via osprofiler +websocket-client==1.9.0 + # via kubernetes +websockets==16.0 + # via juju +wrapt==2.2.1 + # via + # debtcollector + # python-glanceclient +yarl==1.24.2 + # via aiohttp +zaza==2024.1.1 + # via + # -r test-requirements.in + # zaza-openstack +zaza-openstack @ git+https://github.com/openstack-charmers/zaza-openstack-tests.git@stable/bobcat + # via -r test-requirements.in +zipp==4.1.0 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# juju +# kubernetes diff --git a/metadata.yaml b/metadata.yaml index 5234aeb..6480e81 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -13,7 +13,6 @@ tags: - misc series: - jammy -- lunar - mantic extra-bindings: public: diff --git a/osci.yaml b/osci.yaml index 134485d..432e73e 100644 --- a/osci.yaml +++ b/osci.yaml @@ -6,4 +6,4 @@ needs_charm_build: true charm_build_name: glance build_type: charmcraft - charmcraft_channel: 2.x/stable + charmcraft_channel: 3.x/stable diff --git a/requirements.txt b/requirements.in similarity index 100% rename from requirements.txt rename to requirements.in diff --git a/templates/yoga/api-paste.ini b/templates/yoga/api-paste.ini new file mode 100644 index 0000000..dc8687b --- /dev/null +++ b/templates/yoga/api-paste.ini @@ -0,0 +1,86 @@ +# Use this pipeline for no auth or image caching - DEFAULT +[pipeline:glance-api] +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context rootapp + +# Use this pipeline for image caching and no auth +[pipeline:glance-api-caching] +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context cache rootapp + +# Use this pipeline for caching w/ management interface but no auth +[pipeline:glance-api-cachemanagement] +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler unauthenticated-context cache cachemanage rootapp + +# Use this pipeline for keystone auth +[pipeline:glance-api-keystone] +{% if audit_middleware and service_name -%} +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken audit context rootapp +{% else %} +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken context rootapp +{% endif %} + +# Use this pipeline for keystone auth with image caching +[pipeline:glance-api-keystone+caching] +{% if audit_middleware and service_name -%} +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken audit context cache rootapp +{% else %} +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken context cache rootapp +{% endif %} + +# Use this pipeline for keystone auth with caching and cache management +[pipeline:glance-api-keystone+cachemanagement] +{% if audit_middleware and service_name -%} +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken audit context cache cachemanage rootapp +{% else %} +pipeline = cors healthcheck http_proxy_to_wsgi versionnegotiation osprofiler authtoken context cache cachemanage rootapp +{% endif %} + +[composite:rootapp] +paste.composite_factory = glance.api:root_app_factory +/: apiversions +/v2: apiv2app + +[app:apiversions] +paste.app_factory = glance.api.versions:create_resource + +[app:apiv2app] +paste.app_factory = glance.api.v2.router:API.factory + +[filter:healthcheck] +paste.filter_factory = oslo_middleware:Healthcheck.factory +backends = disable_by_file +disable_by_file_path = /etc/glance/healthcheck_disable + +[filter:versionnegotiation] +paste.filter_factory = glance.api.middleware.version_negotiation:VersionNegotiationFilter.factory + +[filter:cache] +paste.filter_factory = glance.api.middleware.cache:CacheFilter.factory + +[filter:cachemanage] +paste.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter.factory + +[filter:context] +paste.filter_factory = glance.api.middleware.context:ContextMiddleware.factory + +[filter:unauthenticated-context] +paste.filter_factory = glance.api.middleware.context:UnauthenticatedContextMiddleware.factory + +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory +delay_auth_decision = true + +[filter:gzip] +paste.filter_factory = glance.api.middleware.gzip:GzipMiddleware.factory + +[filter:osprofiler] +paste.filter_factory = osprofiler.web:WsgiMiddleware.factory + +[filter:cors] +paste.filter_factory = oslo_middleware.cors:filter_factory +oslo_config_project = glance +oslo_config_program = glance-api + +[filter:http_proxy_to_wsgi] +paste.filter_factory = oslo_middleware:HTTPProxyToWSGI.factory + +{% include "section-filter-audit" %} \ No newline at end of file diff --git a/templates/yoga/api_audit_map.conf b/templates/yoga/api_audit_map.conf new file mode 100644 index 0000000..fc9e461 --- /dev/null +++ b/templates/yoga/api_audit_map.conf @@ -0,0 +1,16 @@ +[DEFAULT] +# default target endpoint type +# should match the endpoint type defined in service catalog +target_endpoint_type = None + +# possible end path of api requests +[path_keywords] +detail = None +file = None +images = image +members = member +tags = tag + +# map endpoint type defined in service catalog to CADF typeURI +[service_endpoints] +image = service/storage/image \ No newline at end of file diff --git a/templates/yoga/glance-api.conf b/templates/yoga/glance-api.conf new file mode 100644 index 0000000..6aed2b4 --- /dev/null +++ b/templates/yoga/glance-api.conf @@ -0,0 +1,89 @@ +[DEFAULT] +verbose = {{ verbose }} +use_syslog = {{ use_syslog }} +debug = {{ debug }} +workers = {{ workers }} +bind_host = {{ bind_host }} + +{% if ext -%} +bind_port = {{ ext }} +{% elif bind_port -%} +bind_port = {{ bind_port }} +{% else -%} +bind_port = 9292 +{% endif -%} + +{% if transport_url %} +transport_url = {{ transport_url }} +{% endif %} + +log_file = /var/log/glance/api.log +backlog = 4096 + +{% if expose_image_locations -%} +show_multiple_locations = {{ expose_image_locations }} +show_image_direct_url = {{ expose_image_locations }} +{% endif -%} + +{% if api_config_flags -%} +{% for key, value in api_config_flags.items() -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif -%} + +delayed_delete = False +scrub_time = 43200 +scrubber_datadir = /var/lib/glance/scrubber +image_cache_dir = /var/lib/glance/image-cache/ +db_enforce_mysql_charset = False + +{% if image_size_cap -%} +image_size_cap = {{ image_size_cap }} +{% endif -%} + +{% if enabled_backends %} +enabled_backends = {{ enabled_backends }} +{% endif %} + +[glance_store] +{% if default_store_backend %} +default_backend = {{ default_store_backend }} +{% endif %} + +[image_format] +disk_formats = {{ disk_formats }} +{% if container_formats -%} +container_formats = {{ container_formats }} +{% endif -%} + +{% include "section-keystone-authtoken-v3only" %} + +{% if auth_host -%} +[paste_deploy] +flavor = keystone +config_file = /etc/glance/api-paste.ini +{% endif %} + +[barbican] +auth_endpoint = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v3 + +{% include "parts/section-database" %} + +{% include "section-oslo-messaging-rabbit" %} + +{% include "section-oslo-notifications" %} + +{% include "section-oslo-middleware" %} + +{% include "parts/section-storage" %} + +{% for name, cfg in enabled_backend_configs.items() %} +[{{name}}] +{% for key, val in cfg.items() -%} +{{ key }} = {{ val }} +{% endfor -%} +{% endfor%} + +{% include "parts/section-image-import" %} + +{% include "section-audit-middleware-notifications" %} \ No newline at end of file diff --git a/test-requirements-py310.txt b/test-requirements-py310.txt new file mode 100644 index 0000000..710e861 --- /dev/null +++ b/test-requirements-py310.txt @@ -0,0 +1,750 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --output-file=test-requirements-py310.txt --unsafe-package=juju --unsafe-package=kubernetes test-requirements.in +# +aiohappyeyeballs==2.6.2 + # via aiohttp +aiohttp==3.14.0 + # via + # python-libmaas + # zaza +aiosignal==1.4.0 + # via aiohttp +aodhclient==3.11.0 + # via zaza-openstack +argcomplete==3.6.3 + # via python-libmaas +async-generator==1.10 + # via + # zaza + # zaza-openstack +async-timeout==5.0.1 + # via aiohttp +attrs==26.1.0 + # via + # aiohttp + # jsonschema +babel==2.18.0 + # via + # python-cinderclient + # python-heatclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient +backports-datetime-fromisoformat==2.0.3 + # via juju +backports-strenum==1.3.1 + # via juju +bcrypt==5.0.0 + # via paramiko +blessings==1.7 + # via charm-tools +boto3==1.43.22 + # via zaza-openstack +botocore==1.43.22 + # via + # boto3 + # s3transfer +certifi==2026.5.20 + # via + # kubernetes + # requests +cffi==2.0.0 + # via + # cryptography + # pynacl +charm-tools @ git+https://github.com/juju/charm-tools.git + # via -r test-requirements.in +charset-normalizer==3.4.7 + # via requests +cheetah3==3.2.6.post1 + # via charm-tools +cliff==2.18.0 + # via + # -r test-requirements.in + # aodhclient + # gnocchiclient + # osc-lib + # python-barbicanclient + # python-cloudkittyclient + # python-designateclient + # python-heatclient + # python-ironicclient + # python-neutronclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient + # stestr +cmd2==0.8.9 + # via cliff +colander==1.8.3 + # via charm-tools +colorclass==2.2.2 + # via python-libmaas +coverage==7.14.1 + # via -r test-requirements.in +croniter==6.2.2 + # via -r test-requirements.in +cryptography==3.3.2 + # via + # openstacksdk + # paramiko + # pyopenssl + # python-magnumclient + # secretstorage + # trustme + # zaza + # zaza-openstack +debtcollector==3.1.0 + # via + # gnocchiclient + # oslo-concurrency + # oslo-config + # oslo-log + # python-designateclient + # python-keystoneclient + # python-manilaclient + # python-neutronclient +decorator==5.3.1 + # via + # dogpile-cache + # jsonpath-rw + # openstacksdk + # python-magnumclient +dict2colander==0.2 + # via charm-tools +distlib==0.4.1 + # via virtualenv +dnspython==2.8.0 + # via + # pymongo + # zaza-openstack +dogpile-cache==1.5.0 + # via + # openstacksdk + # python-ironicclient +fasteners==0.20 + # via oslo-concurrency +filelock==3.29.1 + # via virtualenv +fixtures==4.3.2 + # via stestr +flake8==7.1.1 + # via -r test-requirements.in +frozenlist==1.8.0 + # via + # aiohttp + # aiosignal +futurist==1.10.0 + # via + # gnocchiclient + # zaza-openstack +gnocchiclient==7.2.0 + # via zaza-openstack +google-auth==2.47.0 + # via kubernetes +hvac==0.6.4 + # via + # juju + # zaza + # zaza-openstack +idna==3.18 + # via + # requests + # trustme + # yarl +importlib-metadata==9.0.0 + # via keyring +invoke==3.0.3 + # via paramiko +iso8601==2.1.0 + # via + # colander + # gnocchiclient + # keystoneauth1 + # openstacksdk + # oslo-utils + # python-ceilometerclient + # python-heatclient + # python-neutronclient + # python-novaclient + # python-subunit +jaraco-classes==3.4.0 + # via keyring +jeepney==0.9.0 + # via + # keyring + # secretstorage +jinja2==3.1.6 + # via + # zaza + # zaza-openstack +jmespath==1.1.0 + # via + # boto3 + # botocore + # openstacksdk +jsonpatch==1.33 + # via + # openstacksdk + # warlock +jsonpath-rw==1.4.0 + # via jsonpath-rw-ext +jsonpath-rw-ext==1.2.2 + # via python-cloudkittyclient +jsonpointer==3.1.1 + # via jsonpatch +jsonschema==4.17.3 + # via + # charm-tools + # python-designateclient + # python-ironicclient + # warlock +juju-wait==2.8.4 + # via zaza +jujubundlelib==0.5.7 + # via charm-tools +keyring==23.13.1 + # via charm-tools +keystoneauth1==5.14.0 + # via + # aodhclient + # gnocchiclient + # openstacksdk + # osc-lib + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-cloudkittyclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient +lxml==6.1.1 + # via zaza-openstack +macaroonbakery==1.3.4 + # via + # juju + # python-libmaas + # zaza +markupsafe==3.0.3 + # via jinja2 +mccabe==0.7.0 + # via flake8 +more-itertools==11.1.0 + # via jaraco-classes +msgpack==1.1.2 + # via oslo-serialization +multidict==6.7.1 + # via + # aiohttp + # yarl +mypy-extensions==1.1.0 + # via typing-inspect +netaddr==1.3.0 + # via + # oslo-config + # oslo-utils + # osprofiler + # python-neutronclient +netifaces==0.11.0 + # via python-octaviaclient +oauthlib==3.3.1 + # via + # kubernetes + # python-libmaas + # requests-oauthlib +openstacksdk==4.13.0 + # via + # os-client-config + # osc-lib + # python-ironicclient + # python-magnumclient + # python-openstackclient +os-client-config==2.3.0 + # via + # python-cloudkittyclient + # python-neutronclient +os-service-types==1.8.2 + # via + # keystoneauth1 + # openstacksdk +osc-lib==2.1.0 + # via + # aodhclient + # python-cloudkittyclient + # python-designateclient + # python-heatclient + # python-ironicclient + # python-magnumclient + # python-neutronclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient + # zaza-openstack +oslo-concurrency==7.5.0 + # via osprofiler +oslo-config==6.11.3 + # via + # oslo-concurrency + # oslo-log + # osprofiler + # python-keystoneclient + # python-manilaclient + # zaza + # zaza-openstack +oslo-context==6.4.0 + # via oslo-log +oslo-i18n==6.8.0 + # via + # aodhclient + # osc-lib + # oslo-concurrency + # oslo-config + # oslo-log + # oslo-utils + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-glanceclient + # python-heatclient + # python-keystoneclient + # python-magnumclient + # python-neutronclient + # python-novaclient + # python-openstackclient + # python-watcherclient +oslo-log==8.2.0 + # via + # python-cloudkittyclient + # python-magnumclient + # python-manilaclient + # python-neutronclient +oslo-serialization==5.10.0 + # via + # aodhclient + # oslo-log + # osprofiler + # python-barbicanclient + # python-ceilometerclient + # python-designateclient + # python-heatclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-watcherclient +oslo-utils==10.1.0 + # via + # aodhclient + # osc-lib + # oslo-concurrency + # oslo-log + # oslo-serialization + # osprofiler + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-cloudkittyclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient +osprofiler==4.4.0 + # via aodhclient +otherstuf==1.1.0 + # via charm-tools +packaging==26.2 + # via + # juju + # oslo-utils +paramiko==5.0.0 + # via juju +parse==1.22.1 + # via stuf +path==16.16.0 + # via charm-tools +pathspec==0.10.3 + # via charm-tools +pbr==7.0.3 + # via + # aodhclient + # cliff + # futurist + # jsonpath-rw-ext + # keystoneauth1 + # openstacksdk + # os-client-config + # os-service-types + # osc-lib + # oslo-concurrency + # oslo-context + # oslo-i18n + # oslo-log + # oslo-utils + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-cloudkittyclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-watcherclient +pika==1.4.1 + # via zaza-openstack +pip==26.1.2 + # via charm-tools +platformdirs==4.10.0 + # via + # openstacksdk + # python-ironicclient + # virtualenv +ply==3.11 + # via jsonpath-rw +prettytable==0.7.2 + # via + # cliff + # futurist + # osprofiler + # python-ceilometerclient + # python-cinderclient + # python-glanceclient + # python-heatclient + # python-magnumclient + # python-manilaclient + # python-novaclient +propcache==0.5.2 + # via + # aiohttp + # yarl +protobuf==7.35.0 + # via macaroonbakery +psutil==7.2.2 + # via + # -r test-requirements.in + # openstacksdk + # oslo-utils +pyasn1==0.6.3 + # via + # juju + # pyasn1-modules + # rsa +pyasn1-modules==0.4.2 + # via google-auth +pycodestyle==2.12.1 + # via flake8 +pycparser==3.0 + # via cffi +pyflakes==3.2.0 + # via flake8 +pymacaroons==0.13.0 + # via macaroonbakery +pymongo==4.17.0 + # via python-libmaas +pynacl==1.6.2 + # via + # macaroonbakery + # paramiko + # pymacaroons +pyopenssl==21.0.0 + # via + # python-glanceclient + # zaza-openstack +pyparsing==2.4.7 + # via + # -r test-requirements.in + # aodhclient + # cliff + # cmd2 + # oslo-utils +pyperclip==1.11.0 + # via cmd2 +pyrfc3339==1.1 + # via macaroonbakery +pyrsistent==0.20.0 + # via jsonschema +python-barbicanclient==4.10.0 + # via zaza-openstack +python-ceilometerclient==2.9.0 + # via zaza-openstack +python-cinderclient==5.0.2 + # via + # python-openstackclient + # zaza-openstack +python-cloudkittyclient==4.1.0 + # via zaza-openstack +python-dateutil==2.9.0.post0 + # via + # botocore + # croniter + # gnocchiclient + # kubernetes + # oslo-log +python-designateclient==2.12.0 + # via zaza-openstack +python-glanceclient==4.12.0 + # via + # python-openstackclient + # zaza-openstack +python-heatclient==1.18.1 + # via zaza-openstack +python-ironicclient==6.1.0 + # via zaza-openstack +python-keystoneclient==3.21.0 + # via + # python-manilaclient + # python-neutronclient + # python-openstackclient + # zaza-openstack +python-libmaas==0.6.8 + # via zaza +python-magnumclient==4.10.0 + # via zaza-openstack +python-manilaclient==1.29.0 + # via zaza-openstack +python-neutronclient==6.14.1 + # via + # python-octaviaclient + # zaza-openstack +python-novaclient==15.1.1 + # via + # python-openstackclient + # zaza-openstack +python-octaviaclient==1.10.1 + # via zaza-openstack +python-openstackclient==4.0.2 + # via python-octaviaclient +python-subunit==1.4.6 + # via stestr +python-swiftclient==3.8.1 + # via + # python-heatclient + # zaza-openstack +python-watcherclient==4.10.0 + # via zaza-openstack +pytz==2026.2 + # via + # pyrfc3339 + # python-libmaas +pyudev==0.24.4 + # via -r test-requirements.in +pyyaml==6.0.3 + # via + # charm-tools + # cliff + # juju + # juju-wait + # jujubundlelib + # kubernetes + # openstacksdk + # oslo-config + # oslo-utils + # python-cloudkittyclient + # python-heatclient + # python-ironicclient + # python-libmaas + # python-subunit + # python-watcherclient + # stestr + # zaza + # zaza-openstack +requests==2.34.2 + # via + # -r test-requirements.in + # charm-tools + # hvac + # keystoneauth1 + # kubernetes + # macaroonbakery + # oslo-config + # osprofiler + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-designateclient + # python-glanceclient + # python-heatclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient + # python-manilaclient + # python-neutronclient + # python-octaviaclient + # python-swiftclient + # requests-oauthlib +requests-oauthlib==2.0.0 + # via kubernetes +requirements-parser==0.5.0 + # via charm-tools +rfc3986==2.0.0 + # via oslo-config +rsa==4.9.1 + # via google-auth +ruamel-yaml==0.17.40 + # via charm-tools +ruamel-yaml-clib==0.2.15 + # via ruamel-yaml +s3transfer==0.18.0 + # via boto3 +secretstorage==3.3.3 + # via + # charm-tools + # keyring +setuptools==81.0.0 + # via + # -r test-requirements.in + # charm-tools + # colander + # pbr +simplejson==4.1.1 + # via + # osc-lib + # python-cinderclient + # python-manilaclient + # python-neutronclient + # python-novaclient +six==1.17.0 + # via + # blessings + # cliff + # cmd2 + # cryptography + # futurist + # jsonpath-rw + # kubernetes + # macaroonbakery + # oslo-config + # pymacaroons + # pyopenssl + # python-barbicanclient + # python-ceilometerclient + # python-cinderclient + # python-dateutil + # python-designateclient + # python-heatclient + # python-keystoneclient + # python-manilaclient + # python-neutronclient + # python-novaclient + # python-octaviaclient + # python-openstackclient + # python-swiftclient +stestr==4.2.1 + # via -r test-requirements.in +stevedore==5.8.0 + # via + # cliff + # dogpile-cache + # keystoneauth1 + # osc-lib + # oslo-config + # python-ceilometerclient + # python-designateclient + # python-ironicclient + # python-keystoneclient + # python-magnumclient +stuf==0.9.16 + # via otherstuf +tenacity==9.1.4 + # via + # zaza + # zaza-openstack +terminaltables==3.1.10 + # via python-libmaas +testtools==2.9.1 + # via + # python-subunit + # stestr +tomlkit==0.15.0 + # via stestr +toposort==1.10 + # via juju +translationstring==1.4 + # via colander +trustme==1.2.1 + # via zaza-openstack +types-setuptools==82.0.0.20260518 + # via requirements-parser +typing-extensions==4.15.0 + # via + # aiohttp + # aiosignal + # dogpile-cache + # juju + # keystoneauth1 + # multidict + # openstacksdk + # os-service-types + # oslo-context + # typing-inspect + # virtualenv +typing-inspect==0.9.0 + # via juju +ujson==5.12.1 + # via gnocchiclient +urllib3==2.7.0 + # via + # botocore + # kubernetes + # requests +virtualenv==20.39.1 + # via charm-tools +voluptuous==0.16.0 + # via stestr +warlock==2.1.0 + # via python-glanceclient +wcwidth==0.7.0 + # via cmd2 +webob==1.8.10 + # via osprofiler +websocket-client==1.9.0 + # via kubernetes +websockets==16.0 + # via juju +wrapt==2.2.1 + # via + # debtcollector + # python-glanceclient +yarl==1.24.2 + # via aiohttp +zaza==2024.1.1 + # via + # -r test-requirements.in + # zaza-openstack +zaza-openstack @ git+https://github.com/openstack-charmers/zaza-openstack-tests.git@stable/bobcat + # via -r test-requirements.in +zipp==4.1.0 + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# juju +# kubernetes diff --git a/test-requirements.txt b/test-requirements.in similarity index 85% rename from test-requirements.txt rename to test-requirements.in index e972406..76fd691 100644 --- a/test-requirements.txt +++ b/test-requirements.in @@ -19,11 +19,11 @@ cliff<3.0.0 coverage>=4.5.2 pyudev # for ceph-* charm unit tests (need to fix the ceph-* charm unit tests/mocking) -git+https://github.com/openstack-charmers/zaza.git#egg=zaza -git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack - -# Needed for charm-glance: -git+https://opendev.org/openstack/tempest.git#egg=tempest +zaza==2024.* +git+https://github.com/openstack-charmers/zaza-openstack-tests.git@stable/bobcat#egg=zaza.openstack croniter # needed for charm-rabbitmq-server unit tests psutil +setuptools<82.0.0 +git+https://github.com/juju/charm-tools.git +flake8==7.1.1 diff --git a/tests/bundles/jammy-antelope.yaml b/tests/bundles/jammy-antelope.yaml index 9770052..59997bf 100644 --- a/tests/bundles/jammy-antelope.yaml +++ b/tests/bundles/jammy-antelope.yaml @@ -31,13 +31,13 @@ applications: keystone-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge glance-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge cinder-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge mysql-innodb-cluster: charm: ch:mysql-innodb-cluster @@ -46,7 +46,7 @@ applications: - '0' - '1' - '2' - channel: latest/edge + channel: 8.0/edge ceph-osd: charm: ch:ceph-osd @@ -62,7 +62,7 @@ applications: - '6' - '7' - '8' - channel: latest/edge + channel: reef/edge ceph-radosgw: charm: ch:ceph-radosgw @@ -71,7 +71,7 @@ applications: source: *openstack-origin to: - '15' - channel: latest/edge + channel: reef/edge ceph-mon: charm: ch:ceph-mon @@ -83,14 +83,14 @@ applications: - '9' - '10' - '11' - channel: latest/edge + channel: reef/edge rabbitmq-server: charm: ch:rabbitmq-server num_units: 1 to: - '12' - channel: latest/edge + channel: 3.9/edge keystone: expose: True @@ -100,11 +100,11 @@ applications: openstack-origin: *openstack-origin to: - '13' - channel: latest/edge + channel: 2023.2/edge glance: expose: True - charm: ../../glance.charm + charm: ../../glance_ubuntu@22.04-amd64.charm num_units: 1 options: openstack-origin: *openstack-origin @@ -127,7 +127,7 @@ applications: block-device: None to: - '16' - channel: latest/edge + channel: 2023.2/edge cinder-lvm: charm: ch:cinder-lvm @@ -138,7 +138,7 @@ applications: ephemeral-unmount: /mnt allocation-type: auto config-flags: target_helper=lioadm - channel: latest/edge + channel: 2023.2/edge relations: - - 'keystone:shared-db' diff --git a/tests/bundles/jammy-bobcat.yaml b/tests/bundles/jammy-bobcat.yaml index 49d29fa..e7c2ef3 100644 --- a/tests/bundles/jammy-bobcat.yaml +++ b/tests/bundles/jammy-bobcat.yaml @@ -31,13 +31,13 @@ applications: keystone-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge glance-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge cinder-mysql-router: charm: ch:mysql-router - channel: latest/edge + channel: 8.0/edge mysql-innodb-cluster: charm: ch:mysql-innodb-cluster @@ -46,7 +46,7 @@ applications: - '0' - '1' - '2' - channel: latest/edge + channel: 8.0/edge ceph-osd: charm: ch:ceph-osd @@ -62,7 +62,7 @@ applications: - '6' - '7' - '8' - channel: latest/edge + channel: reef/edge ceph-radosgw: charm: ch:ceph-radosgw @@ -71,7 +71,7 @@ applications: source: *openstack-origin to: - '15' - channel: latest/edge + channel: reef/edge ceph-mon: charm: ch:ceph-mon @@ -83,14 +83,14 @@ applications: - '9' - '10' - '11' - channel: latest/edge + channel: reef/edge rabbitmq-server: charm: ch:rabbitmq-server num_units: 1 to: - '12' - channel: latest/edge + channel: 3.9/edge keystone: expose: True @@ -100,11 +100,11 @@ applications: openstack-origin: *openstack-origin to: - '13' - channel: latest/edge + channel: 2023.2/edge glance: expose: True - charm: ../../glance.charm + charm: ../../glance_ubuntu@22.04-amd64.charm num_units: 1 options: openstack-origin: *openstack-origin @@ -127,7 +127,7 @@ applications: block-device: None to: - '16' - channel: latest/edge + channel: 2023.2/edge cinder-lvm: charm: ch:cinder-lvm @@ -138,7 +138,7 @@ applications: ephemeral-unmount: /mnt allocation-type: auto config-flags: target_helper=lioadm - channel: latest/edge + channel: 2023.2/edge relations: - - 'keystone:shared-db' diff --git a/tests/bundles/lunar-antelope.yaml b/tests/bundles/lunar-antelope.yaml deleted file mode 100644 index dda2379..0000000 --- a/tests/bundles/lunar-antelope.yaml +++ /dev/null @@ -1,189 +0,0 @@ -variables: - openstack-origin: &openstack-origin distro - -series: lunar - -comment: -- 'machines section to decide order of deployment. database sooner = faster' -machines: - '0': - constraints: mem=3072M - '1': - constraints: mem=3072M - '2': - constraints: mem=3072M - '3': - '4': - '5': - '6': - '7': - '8': - '9': - '10': - '11': - '12': - '13': - '14': - '15': - '16': - -applications: - - keystone-mysql-router: - charm: ch:mysql-router - channel: latest/edge - glance-mysql-router: - charm: ch:mysql-router - channel: latest/edge - cinder-mysql-router: - charm: ch:mysql-router - channel: latest/edge - - mysql-innodb-cluster: - charm: ch:mysql-innodb-cluster - num_units: 3 - to: - - '0' - - '1' - - '2' - channel: latest/edge - - ceph-osd: - charm: ch:ceph-osd - num_units: 6 - storage: - osd-devices: '10G' - options: - source: *openstack-origin - to: - - '3' - - '4' - - '5' - - '6' - - '7' - - '8' - channel: latest/edge - - ceph-radosgw: - charm: ch:ceph-radosgw - num_units: 1 - options: - source: *openstack-origin - to: - - '15' - channel: latest/edge - - ceph-mon: - charm: ch:ceph-mon - num_units: 3 - options: - source: *openstack-origin - monitor-count: '3' - to: - - '9' - - '10' - - '11' - channel: latest/edge - - rabbitmq-server: - charm: ch:rabbitmq-server - num_units: 1 - to: - - '12' - channel: latest/edge - - keystone: - expose: True - charm: ch:keystone - num_units: 1 - options: - openstack-origin: *openstack-origin - to: - - '13' - channel: latest/edge - - glance: - expose: True - charm: ../../glance.charm - num_units: 1 - options: - openstack-origin: *openstack-origin - pool-type: erasure-coded - ec-profile-k: 4 - ec-profile-m: 2 - ec-profile-plugin: jerasure - to: - - '14' - - cinder: - expose: True - charm: ch:cinder - num_units: 1 - storage: - block-devices: '10G' - options: - openstack-origin: *openstack-origin - glance-api-version: 2 - block-device: None - to: - - '16' - channel: latest/edge - - cinder-lvm: - charm: ch:cinder-lvm - options: - block-device: '/tmp/vol1|4G' - alias: zaza-lvm - overwrite: "true" - ephemeral-unmount: /mnt - allocation-type: auto - config-flags: target_helper=lioadm - channel: latest/edge - -relations: - - - 'keystone:shared-db' - - 'keystone-mysql-router:shared-db' - - - 'keystone-mysql-router:db-router' - - 'mysql-innodb-cluster:db-router' - - - - 'glance:shared-db' - - 'glance-mysql-router:shared-db' - - - 'glance-mysql-router:db-router' - - 'mysql-innodb-cluster:db-router' - - - - 'glance:identity-service' - - 'keystone:identity-service' - - - - 'glance:amqp' - - 'rabbitmq-server:amqp' - - - - 'glance:ceph' - - 'ceph-mon:client' - - - - 'ceph-osd:mon' - - 'ceph-mon:osd' - - - - 'ceph-radosgw:mon' - - 'ceph-mon:radosgw' - - - 'ceph-radosgw:identity-service' - - 'keystone:identity-service' - - - 'ceph-radosgw:object-store' - - 'glance:object-store' - - - - 'cinder:shared-db' - - 'cinder-mysql-router:shared-db' - - - 'cinder-mysql-router:db-router' - - 'mysql-innodb-cluster:db-router' - - - - 'cinder:identity-service' - - 'keystone:identity-service' - - - - 'cinder:amqp' - - 'rabbitmq-server:amqp' - - - - 'cinder:image-service' - - 'glance:image-service' - - - 'cinder:cinder-volume-service' - - 'glance:cinder-volume-service' - - - 'cinder-lvm:storage-backend' - - 'cinder:storage-backend' diff --git a/tests/bundles/mantic-bobcat.yaml b/tests/bundles/mantic-bobcat.yaml deleted file mode 100644 index 01a4d20..0000000 --- a/tests/bundles/mantic-bobcat.yaml +++ /dev/null @@ -1,189 +0,0 @@ -variables: - openstack-origin: &openstack-origin distro - -series: mantic - -comment: -- 'machines section to decide order of deployment. database sooner = faster' -machines: - '0': - constraints: mem=3072M - '1': - constraints: mem=3072M - '2': - constraints: mem=3072M - '3': - '4': - '5': - '6': - '7': - '8': - '9': - '10': - '11': - '12': - '13': - '14': - '15': - '16': - -applications: - - keystone-mysql-router: - charm: ch:mysql-router - channel: latest/edge - glance-mysql-router: - charm: ch:mysql-router - channel: latest/edge - cinder-mysql-router: - charm: ch:mysql-router - channel: latest/edge - - mysql-innodb-cluster: - charm: ch:mysql-innodb-cluster - num_units: 3 - to: - - '0' - - '1' - - '2' - channel: latest/edge - - ceph-osd: - charm: ch:ceph-osd - num_units: 6 - storage: - osd-devices: '10G' - options: - source: *openstack-origin - to: - - '3' - - '4' - - '5' - - '6' - - '7' - - '8' - channel: latest/edge - - ceph-radosgw: - charm: ch:ceph-radosgw - num_units: 1 - options: - source: *openstack-origin - to: - - '15' - channel: latest/edge - - ceph-mon: - charm: ch:ceph-mon - num_units: 3 - options: - source: *openstack-origin - monitor-count: '3' - to: - - '9' - - '10' - - '11' - channel: latest/edge - - rabbitmq-server: - charm: ch:rabbitmq-server - num_units: 1 - to: - - '12' - channel: latest/edge - - keystone: - expose: True - charm: ch:keystone - num_units: 1 - options: - openstack-origin: *openstack-origin - to: - - '13' - channel: latest/edge - - glance: - expose: True - charm: ../../glance.charm - num_units: 1 - options: - openstack-origin: *openstack-origin - pool-type: erasure-coded - ec-profile-k: 4 - ec-profile-m: 2 - ec-profile-plugin: jerasure - to: - - '14' - - cinder: - expose: True - charm: ch:cinder - num_units: 1 - storage: - block-devices: '10G' - options: - openstack-origin: *openstack-origin - glance-api-version: 2 - block-device: None - to: - - '16' - channel: latest/edge - - cinder-lvm: - charm: ch:cinder-lvm - options: - block-device: '/tmp/vol1|4G' - alias: zaza-lvm - overwrite: "true" - ephemeral-unmount: /mnt - allocation-type: auto - config-flags: target_helper=lioadm - channel: latest/edge - -relations: - - - 'keystone:shared-db' - - 'keystone-mysql-router:shared-db' - - - 'keystone-mysql-router:db-router' - - 'mysql-innodb-cluster:db-router' - - - - 'glance:shared-db' - - 'glance-mysql-router:shared-db' - - - 'glance-mysql-router:db-router' - - 'mysql-innodb-cluster:db-router' - - - - 'glance:identity-service' - - 'keystone:identity-service' - - - - 'glance:amqp' - - 'rabbitmq-server:amqp' - - - - 'glance:ceph' - - 'ceph-mon:client' - - - - 'ceph-osd:mon' - - 'ceph-mon:osd' - - - - 'ceph-radosgw:mon' - - 'ceph-mon:radosgw' - - - 'ceph-radosgw:identity-service' - - 'keystone:identity-service' - - - 'ceph-radosgw:object-store' - - 'glance:object-store' - - - - 'cinder:shared-db' - - 'cinder-mysql-router:shared-db' - - - 'cinder-mysql-router:db-router' - - 'mysql-innodb-cluster:db-router' - - - - 'cinder:identity-service' - - 'keystone:identity-service' - - - - 'cinder:amqp' - - 'rabbitmq-server:amqp' - - - - 'cinder:image-service' - - 'glance:image-service' - - - 'cinder:cinder-volume-service' - - 'glance:cinder-volume-service' - - - 'cinder-lvm:storage-backend' - - 'cinder:storage-backend' diff --git a/tests/tests.yaml b/tests/tests.yaml index 4ebcece..3214bea 100644 --- a/tests/tests.yaml +++ b/tests/tests.yaml @@ -11,8 +11,6 @@ gate_bundles: dev_bundles: - jammy-bobcat - - lunar-antelope - - mantic-bobcat configure: - zaza.openstack.charm_tests.glance.setup.add_lts_image @@ -29,6 +27,7 @@ tests: - zaza.openstack.charm_tests.glance.tests.GlanceCephRGWBackendTest - zaza.openstack.charm_tests.glance.tests.GlanceExternalS3Test - zaza.openstack.charm_tests.glance.tests.GlanceCinderBackendTest + - zaza.openstack.charm_tests.audit.tests.KeystoneAuditMiddlewareTest - zaza.openstack.charm_tests.policyd.tests.GlanceTests - zaza.openstack.charm_tests.ceph.tests.CheckPoolTypes - zaza.openstack.charm_tests.ceph.tests.BlueStoreCompressionCharmOperation @@ -38,11 +37,10 @@ tests: - zaza.openstack.charm_tests.policyd.tests.GlanceTests tests_options: + audit-middleware: + service: glance tempest: full_run: smoke: True policyd: service: glance - force_deploy: - - lunar-antelope - - mantic-bobcat diff --git a/tox.ini b/tox.ini index 2cb6ca1..db68947 100644 --- a/tox.ini +++ b/tox.ini @@ -3,10 +3,7 @@ # within individual charm repos. See the 'global' dir contents for available # choices of tox.ini for OpenStack Charms: # https://github.com/openstack-charmers/release-tools -# -# TODO: Distill the func test requirements from the lint/unit test -# requirements. They are intertwined. Also, Zaza itself should specify -# all of its own requirements and if it doesn't, fix it there. + [tox] envlist = pep8,py3 # NOTE: Avoid build/test env pollution by not enabling sitepackages. @@ -15,61 +12,58 @@ sitepackages = False skip_missing_interpreters = False [testenv] +basepython = python3.10 # We use tox mainly for virtual environment management for test requirements # and do not install the charm code as a Python package into that environment. # Ref: https://tox.wiki/en/latest/config.html#skip_install skip_install = True setenv = VIRTUAL_ENV={envdir} PYTHONHASHSEED=0 - CHARM_DIR={envdir} -commands = stestr run --slowest {posargs} -allowlist_externals = - charmcraft - {toxinidir}/rename.sh passenv = - HOME - TERM CS_* OS_* TEST_* -deps = -r{toxinidir}/test-requirements.txt + # The following are needed for building in environments that use a proxy + # for external access. + http_proxy + https_proxy + no_proxy +allowlist_externals = + charmcraft +deps = + -c {env:TEST_CONSTRAINTS_FILE:https://raw.githubusercontent.com/openstack-charmers/zaza/master/constraints-juju36.txt} + -r{toxinidir}/merged-requirements-py310.txt + +[testenv:update-requirements] +basepython = python3.10 +deps = pip-tools +commands = + pip-compile --unsafe-package juju --unsafe-package kubernetes --output-file=test-requirements-py310.txt test-requirements.in + pip-compile --unsafe-package juju --unsafe-package kubernetes --output-file=merged-requirements-py310.txt requirements.in test-requirements.in [testenv:build] -basepython = python3 -deps = -r{toxinidir}/build-requirements.txt +deps = # charmcraft clean is done to ensure that # `tox -e build` always performs a clean, repeatable build. # For faster rebuilds during development, -# directly run `charmcraft -v pack && ./rename.sh`. +# directly run `charmcraft -v pack commands = charmcraft clean charmcraft -v pack - {toxinidir}/rename.sh charmcraft clean -[testenv:py310] -basepython = python3.10 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt - [testenv:py3] -basepython = python3 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +commands = stestr run --slowest {posargs} + +[testenv:py310] +commands = stestr run --slowest {posargs} [testenv:pep8] -basepython = python3 -deps = flake8==3.9.2 - git+https://github.com/juju/charm-tools.git +deps = -r {toxinidir}/test-requirements-py310.txt commands = flake8 {posargs} hooks unit_tests tests actions lib files charm-proof [testenv:cover] -# Technique based heavily upon -# https://github.com/openstack/nova/blob/master/tox.ini -basepython = python3 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt setenv = {[testenv]setenv} PYTHON=coverage run @@ -93,31 +87,25 @@ omit = unit_tests/* [testenv:venv] -basepython = python3 commands = {posargs} [testenv:func-noop] -basepython = python3 commands = functest-run-suite --help [testenv:func] -basepython = python3 commands = functest-run-suite --keep-model [testenv:func-smoke] -basepython = python3 commands = functest-run-suite --keep-model --smoke [testenv:func-dev] -basepython = python3 commands = functest-run-suite --keep-model --dev [testenv:func-target] -basepython = python3 commands = functest-run-suite --keep-model --bundle {posargs} diff --git a/unit_tests/test_glance_contexts.py b/unit_tests/test_glance_contexts.py index e4749d4..82d65ab 100644 --- a/unit_tests/test_glance_contexts.py +++ b/unit_tests/test_glance_contexts.py @@ -389,7 +389,9 @@ def _relation_ids(*args, **kwargs): 'default_store_backend': 'cinder', }) - def test_multi_backend_with_cinder_volume_types_defined(self): + @patch('charmhelpers.contrib.openstack.' + 'context.IdentityServiceContext.__call__') + def test_multi_backend_with_cinder_volume_types_defined(self, keystone): # return relation_ids only for cinder but not for swift def _relation_ids(*args, **kwargs): if args[0] == 'cinder-volume-service': @@ -399,6 +401,12 @@ def _relation_ids(*args, **kwargs): self.maxDiff = None self.relation_ids.side_effect = _relation_ids + keystone.return_value = { + 'admin_user': 'user', + 'admin_password': 'password', + 'admin_tenant_name': 'services', + 'keystone_authtoken': {'auth_url': 'http://10.0.0.1:35357/v3'}, + } self.is_relation_made.return_value = False data_dir = '/some/data/dir' conf_dict = { @@ -420,6 +428,11 @@ def _relation_ids(*args, **kwargs): 'cinder_volume_type': 'volume-type-test', 'cinder_http_retries': 3, 'cinder_state_transition_timeout': 30, + 'cinder_store_user_name': 'user', + 'cinder_store_password': 'password', + 'cinder_store_project_name': 'services', + 'cinder_store_auth_address': + 'http://10.0.0.1:35357/v3', } }, 'enabled_backends': 'local:file, volume-type-test:cinder', diff --git a/unit_tests/test_glance_utils.py b/unit_tests/test_glance_utils.py index bcacc0a..c7e2c0e 100644 --- a/unit_tests/test_glance_utils.py +++ b/unit_tests/test_glance_utils.py @@ -159,6 +159,7 @@ def test_restart_map_rocky(self): (utils.GLANCE_API_CONF, ['glance-api']), (utils.GLANCE_SWIFT_CONF, ['glance-api']), (utils.GLANCE_POLICY_FILE, ['glance-api', 'glance-registry']), + (utils.GLANCE_API_PASTE, ['glance-api']), (utils.ceph_config_file(), ['glance-api', 'glance-registry']), (utils.HAPROXY_CONF, ['haproxy']), (utils.HTTPS_APACHE_CONF, ['apache2']), @@ -181,6 +182,31 @@ def test_restart_map_stein(self): (utils.GLANCE_API_CONF, ['glance-api']), (utils.GLANCE_SWIFT_CONF, ['glance-api']), (utils.GLANCE_POLICY_FILE, ['glance-api']), + (utils.GLANCE_API_PASTE, ['glance-api']), + (utils.ceph_config_file(), ['glance-api']), + (utils.HAPROXY_CONF, ['haproxy']), + (utils.HTTPS_APACHE_CONF, ['apache2']), + (utils.HTTPS_APACHE_24_CONF, ['apache2']), + (utils.APACHE_PORTS_CONF, ['apache2']), + (utils.MEMCACHED_CONF, ['memcached']), + ]) + self.assertEqual(ex_map, utils.restart_map()) + self.enable_memcache.return_value = False + del ex_map[utils.MEMCACHED_CONF] + self.assertEqual(ex_map, utils.restart_map()) + + def test_restart_map_yoga(self): + self.enable_memcache.return_value = True + self.config.side_effect = None + self.service_name.return_value = 'glance' + self.os_release.return_value = 'yoga' + + ex_map = OrderedDict([ + (utils.GLANCE_API_CONF, ['glance-api']), + (utils.GLANCE_SWIFT_CONF, ['glance-api']), + (utils.GLANCE_POLICY_FILE, ['glance-api']), + (utils.GLANCE_AUDIT_MAP, ['glance-api']), + (utils.GLANCE_API_PASTE, ['glance-api']), (utils.ceph_config_file(), ['glance-api']), (utils.HAPROXY_CONF, ['haproxy']), (utils.HTTPS_APACHE_CONF, ['apache2']), @@ -205,6 +231,7 @@ def test_restart_map_stein_ssl(self, isdir): (utils.GLANCE_API_CONF, ['glance-api']), (utils.GLANCE_SWIFT_CONF, ['glance-api']), (utils.GLANCE_POLICY_FILE, ['glance-api']), + (utils.GLANCE_API_PASTE, ['glance-api']), (utils.ceph_config_file(), ['glance-api']), (utils.HAPROXY_CONF, ['haproxy']), (utils.HTTPS_APACHE_CONF, ['apache2']), @@ -369,10 +396,6 @@ def test_reinstall_paste_ini(self, kv, _os, mock_os_release): call(utils.GLANCE_REGISTRY_PASTE), call(utils.GLANCE_API_PASTE), ]) - _os.remove.assert_has_calls([ - call(utils.GLANCE_REGISTRY_PASTE), - call(utils.GLANCE_API_PASTE), - ]) self.assertTrue(test_kv.get(utils.PASTE_INI_MARKER)) self.assertTrue(test_kv.flushed) @@ -439,6 +462,32 @@ def test_reinstall_paste_ini_fix_upgrade(self, kv, mock_os_release, utils.reinstall_paste_ini() self.assertTrue(self.apt_install.called) + @patch.object(utils, 'os_release') + @patch.object(utils, 'os') + @patch.object(utils, 'kv') + def test_reinstall_paste_ini_rocky_restore(self, kv, _os, mock_os_release): + """Ensure that paste.ini files are restored""" + mock_os_release.return_value = 'rocky' + _os.path.exists.return_value = True + test_kv = SimpleKV() + test_kv.set(utils.PASTE_INI_MARKER, False) + kv.return_value = test_kv + + self.apt_install.reset_mock() + utils.reinstall_paste_ini() + + self.apt_install.assert_called_with( + packages=['glance-common'], + options=utils.REINSTALL_OPTIONS, + fatal=True + ) + reg_paste_backup = f'{utils.GLANCE_REGISTRY_PASTE}.charm.upgrade' + api_paste_backup = f'{utils.GLANCE_API_PASTE}.charm.upgrade' + _os.remove.assert_has_calls([ + call(reg_paste_backup), + call(api_paste_backup), + ]) + def _test_is_api_ready(self, tgt): fake_config = MagicMock() with patch.object(utils, 'incomplete_relation_data') as ird: